(self["webpackChunkviewer"] = self["webpackChunkviewer"] || []).push([["main"],{ /***/ 93955 /*!****************************************************!*\ !*** ./apps/viewer/src/app/app-loading.service.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AppLoadingService: () => (/* binding */ AppLoadingService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); class AppLoadingService { loadingText = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('Loading…', ...(ngDevMode ? [{ debugName: "loadingText" }] : [])); static ɵfac = function AppLoadingService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AppLoadingService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AppLoadingService, factory: AppLoadingService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 18815 /*!************************************!*\ !*** ./apps/viewer/src/app/app.ts ***! \************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ App: () => (/* binding */ App) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/router */ 38709); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_confirmdialog__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/confirmdialog */ 77531); /* harmony import */ var primeng_toast__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/toast */ 73794); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_electron_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/electron-utils */ 63940); /* harmony import */ var _tomoverse_feature__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/feature */ 8938); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _app_loading_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./app-loading.service */ 93955); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @angular/core */ 14975); function App_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](1, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](2, "p", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate"](ctx_r0.appLoading.loadingText()); } } function App_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "section", 8); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](1, "router-outlet"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵclassProp"]("electron-macos", ctx_r0.isElectronMacOS); } } function App_ng_template_5_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](0, "lib-icon", 10); } if (rf & 2) { const conf_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("icon", conf_r2.icon); } } function App_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](1, App_ng_template_5_Conditional_1_Template, 1, 1, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const conf_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](conf_r2.icon ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate"](conf_r2.message); } } function App_ng_template_7_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p-button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("onClick", function App_ng_template_7_Conditional_1_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const confirm_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](4); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](confirm_r4.onAccept()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](1, "p-button", 12); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("onClick", function App_ng_template_7_Conditional_1_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const confirm_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](4); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](confirm_r4.onReject()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); const confirmation_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("buttonProps", confirmation_r5 == null ? null : confirmation_r5.acceptButtonProps)("label", confirmation_r5 == null ? null : confirmation_r5.acceptLabel); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("buttonProps", confirmation_r5 == null ? null : confirmation_r5.rejectButtonProps)("label", confirmation_r5 == null ? null : confirmation_r5.rejectLabel); } } function App_ng_template_7_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p-button", 13); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("onClick", function App_ng_template_7_Conditional_2_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const confirm_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](4); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](confirm_r4.onReject()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](1, "p-button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("onClick", function App_ng_template_7_Conditional_2_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const confirm_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](4); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](confirm_r4.onAccept()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); const confirmation_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("buttonProps", confirmation_r5 == null ? null : confirmation_r5.rejectButtonProps)("label", confirmation_r5 == null ? null : confirmation_r5.rejectLabel); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("buttonProps", confirmation_r5 == null ? null : confirmation_r5.acceptButtonProps)("label", confirmation_r5 == null ? null : confirmation_r5.acceptLabel); } } function App_ng_template_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](1, App_ng_template_7_Conditional_1_Template, 2, 4)(2, App_ng_template_7_Conditional_2_Template, 2, 4); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); const confirm_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](4); const confirmation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵstoreLet"](confirm_r4.confirmation); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"]((confirmation_r7 == null ? null : confirmation_r7.defaultFocus) === "accept" ? 1 : 2); } } class App { log = (0,_tomoverse_feature__WEBPACK_IMPORTED_MODULE_9__.getLogger)(App.name); authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__.AuthService); rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__.RxdbManager); dicomDatabase = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__.DicomDatabaseService); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_2__.Router); appLoading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_app_loading_service__WEBPACK_IMPORTED_MODULE_11__.AppLoadingService); devOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__.DevelopmentOptionsService); isElectronMacOS = (0,_tomoverse_electron_utils__WEBPACK_IMPORTED_MODULE_8__.isElectron)() && typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac OS X'); toastPt = { closeButton: { style: { margin: '0' } }, messageContent: { style: { alignItems: 'center' } }, messageText: { style: { gap: '0' } } }; constructor() { var _this = this; (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const isAuthenticated = _this.authService.isAuthenticated(); yield (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (isAuthenticated) { yield _this.rxdbManager.init(); return; } // Session-scoped peek cache (see DicomDatabaseService.clearPeekCache) must not carry // over into the next login, same reasoning as AuthService.logout clearing preferences. _this.dicomDatabase.clearPeekCache(); yield _this.rxdbManager.remove(); })); })); this.log.debug('Application started'); } ngOnInit() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { if (_this2.authService.isAuthenticated() && _this2.devOptions.clearDicomCacheOnStartup() && (yield _this2.dicomDatabase.hasLocalDicomImports())) { _this2.appLoading.loadingText.set('Clearing local DICOM storage…'); yield _this2.dicomDatabase.clearLocalImports(_this2.getActiveSeriesUid()); } } finally { _this2.appLoading.loadingText.set(undefined); } })(); } getActiveSeriesUid() { // Route: /volume-viewer/:storeUid/:studyUid/:seriesUid/:workSessionUid let route = this.router.routerState.snapshot.root; while (route.firstChild) route = route.firstChild; return route.paramMap.get('seriesUid') ?? undefined; } static ɵfac = function App_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || App)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵdefineComponent"]({ type: App, selectors: [["app-root"]], decls: 9, vars: 2, consts: [["confirm", ""], ["message", ""], ["footer", ""], ["id", "app-loading"], [1, "h-screen", "w-full", "overflow-auto", 3, "electron-macos"], ["position", "top-center", 3, "pt"], ["id", "app-loading-spinner"], ["id", "app-loading-text"], [1, "h-screen", "w-full", "overflow-auto"], [1, "align-items-center", "flex", "flex-row", "gap-3"], [1, "text-3xl", 3, "icon"], ["data-test-id", "app-p-button-confirm-accept", "styleClass", "p-confirm-default-action", 1, "order-2", 3, "onClick", "buttonProps", "label"], ["data-test-id", "app-p-button-confirm-reject", 1, "order-1", 3, "onClick", "buttonProps", "label"], ["data-test-id", "app-p-button-confirm-reject", 3, "onClick", "buttonProps", "label"], ["data-test-id", "app-p-button-confirm-accept", 3, "onClick", "buttonProps", "label"]], template: function App_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](0, App_Conditional_0_Template, 4, 1, "div", 3)(1, App_Conditional_1_Template, 2, 2, "section", 4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](2, "p-toast", 5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](3, "p-confirm-dialog", null, 0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](5, App_ng_template_5_Template, 4, 2, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"])(7, App_ng_template_7_Template, 3, 2, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.appLoading.loadingText() ? 0 : 1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("pt", ctx.toastPt); } }, dependencies: [_angular_router__WEBPACK_IMPORTED_MODULE_3__.RouterModule, _angular_router__WEBPACK_IMPORTED_MODULE_2__.RouterOutlet, primeng_button__WEBPACK_IMPORTED_MODULE_4__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_4__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__.IconComponent, primeng_confirmdialog__WEBPACK_IMPORTED_MODULE_5__.ConfirmDialog, primeng_toast__WEBPACK_IMPORTED_MODULE_6__.ToastModule, primeng_toast__WEBPACK_IMPORTED_MODULE_6__.Toast], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 37407 /*!***********************************************!*\ !*** ./apps/viewer/src/app/runtime-config.ts ***! \***********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getRuntimeConfig: () => (/* binding */ getRuntimeConfig), /* harmony export */ loadRuntimeConfig: () => (/* binding */ loadRuntimeConfig) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); let runtimeConfig = {}; const parseRuntimeConfig = value => { if (typeof value !== 'object' || value === null) return {}; const config = value; return { ...(typeof config['apiUrl'] === 'string' && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.isValidBackendApiUrl)(config['apiUrl']) ? { apiUrl: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.normalizeBackendApiUrl)(config['apiUrl']) } : {}), ...(typeof config['loginRouteRedirect'] === 'string' ? { loginRouteRedirect: config['loginRouteRedirect'] } : {}), ...(typeof config['signUpRouteRedirect'] === 'string' ? { signUpRouteRedirect: config['signUpRouteRedirect'] } : {}), ...(Array.isArray(config['staticHosts']) && config['staticHosts'].every(host => typeof host === 'string') ? { staticHosts: config['staticHosts'] } : {}), ...(typeof config['transferSyntaxUid'] === 'string' ? { transferSyntaxUid: config['transferSyntaxUid'] } : {}) }; }; const loadBundledRuntimeConfig = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const response = yield fetch(`assets/tvct-config.json?version=${Date.now()}`, { cache: 'no-store' }); if (!response.ok) return {}; return parseRuntimeConfig(yield response.json()); } catch { return {}; } }); return function loadBundledRuntimeConfig() { return _ref.apply(this, arguments); }; }(); function loadRuntimeConfig() { return _loadRuntimeConfig.apply(this, arguments); } function _loadRuntimeConfig() { _loadRuntimeConfig = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const bundledConfig = yield loadBundledRuntimeConfig(); if (!globalThis.electronAPI?.getRuntimeConfig) { runtimeConfig = bundledConfig; return runtimeConfig; } try { runtimeConfig = { ...bundledConfig, ...parseRuntimeConfig(yield globalThis.electronAPI.getRuntimeConfig()) }; } catch { runtimeConfig = bundledConfig; } return runtimeConfig; }); return _loadRuntimeConfig.apply(this, arguments); } function getRuntimeConfig() { if (!runtimeConfig.loginRouteRedirect || !runtimeConfig.signUpRouteRedirect || !runtimeConfig.staticHosts || !runtimeConfig.transferSyntaxUid) { throw new Error('Runtime configuration is missing required viewer settings.'); } return runtimeConfig; } /***/ }, /***/ 97283 /*!*********************************!*\ !*** ./apps/viewer/src/main.ts ***! \*********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/platform-browser */ 91486); /* harmony import */ var _app_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./app/app */ 18815); /* harmony import */ var _app_runtime_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app/runtime-config */ 37407); // Prevent trackpad pinch zoom from magnifying the entire page. globalThis.addEventListener('wheel', event => { if (event.ctrlKey) event.preventDefault(); }, { passive: false }); function bootstrap() { return _bootstrap.apply(this, arguments); } // eslint-disable-next-line function _bootstrap() { _bootstrap = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield (0,_app_runtime_config__WEBPACK_IMPORTED_MODULE_3__.loadRuntimeConfig)(); const { appConfig } = yield __webpack_require__.e(/*! import() */ "apps_viewer_src_app_app_config_ts").then(__webpack_require__.bind(__webpack_require__, /*! ./app/app.config */ 36271)); yield (0,_angular_platform_browser__WEBPACK_IMPORTED_MODULE_1__.bootstrapApplication)(_app_app__WEBPACK_IMPORTED_MODULE_2__.App, appConfig); }); return _bootstrap.apply(this, arguments); } void bootstrap().catch(error => console.error(error)); /***/ }, /***/ 19875 /*!*************************************!*\ !*** ./libs/contracts/src/index.ts ***! \*************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CLOUD_RUN_MAX_REQUEST_BYTES: () => (/* reexport safe */ _lib_dicom_upload_limits__WEBPACK_IMPORTED_MODULE_2__.CLOUD_RUN_MAX_REQUEST_BYTES), /* harmony export */ DEFAULT_API_BODY_LIMIT_BYTES: () => (/* reexport safe */ _lib_dicom_upload_limits__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_API_BODY_LIMIT_BYTES), /* harmony export */ MAX_UPLOAD_BATCH_BYTES: () => (/* reexport safe */ _lib_dicom_upload_limits__WEBPACK_IMPORTED_MODULE_2__.MAX_UPLOAD_BATCH_BYTES), /* harmony export */ OT_PAYLOAD_LATEST_VERSION: () => (/* reexport safe */ _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__.OT_PAYLOAD_LATEST_VERSION), /* harmony export */ OT_PAYLOAD_SCHEMA_VERSION: () => (/* reexport safe */ _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__.OT_PAYLOAD_SCHEMA_VERSION), /* harmony export */ WORK_SESSION_LATEST_SCHEMA: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.WORK_SESSION_LATEST_SCHEMA), /* harmony export */ annotationPayloadSchema: () => (/* reexport safe */ _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__.annotationPayloadSchema), /* harmony export */ annotationPayloadV1Schema: () => (/* reexport safe */ _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__.annotationPayloadV1Schema), /* harmony export */ annotationProtocolBindingV1Schema: () => (/* reexport safe */ _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__.annotationProtocolBindingV1Schema), /* harmony export */ annotationSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.annotationSchema), /* harmony export */ dicomInstanceId: () => (/* reexport safe */ _lib_dicom_schema__WEBPACK_IMPORTED_MODULE_0__.dicomInstanceId), /* harmony export */ dicomSchema: () => (/* reexport safe */ _lib_dicom_schema__WEBPACK_IMPORTED_MODULE_0__.dicomSchema), /* harmony export */ dicomSchemaLiteral: () => (/* reexport safe */ _lib_dicom_schema__WEBPACK_IMPORTED_MODULE_0__.dicomSchemaLiteral), /* harmony export */ dicomSeriesId: () => (/* reexport safe */ _lib_dicom_series_schema__WEBPACK_IMPORTED_MODULE_1__.dicomSeriesId), /* harmony export */ dicomSeriesSchema: () => (/* reexport safe */ _lib_dicom_series_schema__WEBPACK_IMPORTED_MODULE_1__.dicomSeriesSchema), /* harmony export */ dicomSeriesSchemaLiteral: () => (/* reexport safe */ _lib_dicom_series_schema__WEBPACK_IMPORTED_MODULE_1__.dicomSeriesSchemaLiteral), /* harmony export */ matrixSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.matrixSchema), /* harmony export */ placeholderSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.placeholderSchema), /* harmony export */ point2Schema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.point2Schema), /* harmony export */ point3Schema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.point3Schema), /* harmony export */ protocolDefinitionSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.protocolDefinitionSchema), /* harmony export */ protocolInstanceSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.protocolInstanceSchema), /* harmony export */ protocolVolumeDataSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.protocolVolumeDataSchema), /* harmony export */ quatSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.quatSchema), /* harmony export */ rxDbAttachmentSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.rxDbAttachmentSchema), /* harmony export */ workSessionJsonSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.workSessionJsonSchema), /* harmony export */ workSessionRxdbJsonSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.workSessionRxdbJsonSchema), /* harmony export */ workSessionSchema: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.workSessionSchema), /* harmony export */ workSessionSchemaWithAttachments: () => (/* reexport safe */ _lib_work_session__WEBPACK_IMPORTED_MODULE_4__.workSessionSchemaWithAttachments) /* harmony export */ }); /* harmony import */ var _lib_dicom_schema__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/dicom.schema */ 77746); /* harmony import */ var _lib_dicom_series_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/dicom-series.schema */ 82096); /* harmony import */ var _lib_dicom_upload_limits__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/dicom-upload-limits */ 99482); /* harmony import */ var _lib_ot_payload__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/ot-payload */ 16520); /* harmony import */ var _lib_work_session__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/work-session */ 32656); /***/ }, /***/ 82096 /*!*******************************************************!*\ !*** ./libs/contracts/src/lib/dicom-series.schema.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ dicomSeriesId: () => (/* binding */ dicomSeriesId), /* harmony export */ dicomSeriesSchema: () => (/* binding */ dicomSeriesSchema), /* harmony export */ dicomSeriesSchemaLiteral: () => (/* binding */ dicomSeriesSchemaLiteral) /* harmony export */ }); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxdb */ 69402); const dicomSeriesId = (storeUid, seriesInstanceUID) => `${storeUid}|${seriesInstanceUID}`; const dicomSeriesSchemaLiteral = { description: 'Stores DICOM series metadata', indexes: ['studyInstanceUID', 'storeUid', 'seriesInstanceUID'], primaryKey: 'id', properties: { createdAt: { type: 'integer' }, id: { maxLength: 300, type: 'string' }, institutionName: { maxLength: 128, type: ['string', 'null'] }, modality: { maxLength: 32, type: ['string', 'null'] }, patientID: { maxLength: 128, type: ['string', 'null'] }, patientName: { maxLength: 128, type: ['string', 'null'] }, seriesDate: { maxLength: 128, type: ['string', 'null'] }, seriesDescription: { maxLength: 256, type: ['string', 'null'] }, seriesInstanceUID: { maxLength: 128, type: 'string' }, seriesNumber: { type: ['integer', 'null'] }, seriesTime: { maxLength: 128, type: ['string', 'null'] }, storeUid: { maxLength: 128, type: 'string' }, studyDate: { maxLength: 128, type: ['string', 'null'] }, studyDescription: { maxLength: 256, type: ['string', 'null'] }, studyInstanceUID: { maxLength: 128, type: 'string' } }, required: ['id', 'seriesInstanceUID', 'studyInstanceUID', 'storeUid'], title: 'Dicom series schema', type: 'object', version: 2 }; const _schemaTyped = (0,rxdb__WEBPACK_IMPORTED_MODULE_0__.toTypedRxJsonSchema)(dicomSeriesSchemaLiteral); const dicomSeriesSchema = dicomSeriesSchemaLiteral; /***/ }, /***/ 99482 /*!*******************************************************!*\ !*** ./libs/contracts/src/lib/dicom-upload-limits.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CLOUD_RUN_MAX_REQUEST_BYTES: () => (/* binding */ CLOUD_RUN_MAX_REQUEST_BYTES), /* harmony export */ DEFAULT_API_BODY_LIMIT_BYTES: () => (/* binding */ DEFAULT_API_BODY_LIMIT_BYTES), /* harmony export */ MAX_UPLOAD_BATCH_BYTES: () => (/* binding */ MAX_UPLOAD_BATCH_BYTES) /* harmony export */ }); /** * Shared between the frontend upload batcher (dicom-api.service.ts) and the API's * body size limit (apps/api/src/main.ts). These three values must stay in this * relationship - MAX_UPLOAD_BATCH_BYTES < DEFAULT_API_BODY_LIMIT_BYTES < * CLOUD_RUN_MAX_REQUEST_BYTES - or a batch the frontend considers safely under * Cloud Run's limit gets silently rejected by the API before it ever reaches * Cloud Run (see TVC-897, TVC-895, TVC-1110 - this has regressed three times). */ // Cloud Run's front end enforces a fixed, unconfigurable ~32MB limit on unary HTTP // request bodies. const CLOUD_RUN_MAX_REQUEST_BYTES = 32 * 1024 * 1024; // Frontend upload batches are capped well under that, leaving headroom for // multipart boundary overhead. const MAX_UPLOAD_BATCH_BYTES = 20 * 1024 * 1024; // The API's own body size limit must sit between the two above, so a batch never // gets rejected by the API before Cloud Run even sees it. const DEFAULT_API_BODY_LIMIT_BYTES = 25 * 1024 * 1024; /***/ }, /***/ 77746 /*!************************************************!*\ !*** ./libs/contracts/src/lib/dicom.schema.ts ***! \************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ dicomInstanceId: () => (/* binding */ dicomInstanceId), /* harmony export */ dicomSchema: () => (/* binding */ dicomSchema), /* harmony export */ dicomSchemaLiteral: () => (/* binding */ dicomSchemaLiteral) /* harmony export */ }); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxdb */ 69402); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const dicomInstanceId = (storeUid, sopInstanceUID) => `${storeUid}|${sopInstanceUID}`; const dicomSchemaLiteral = { attachments: { encrypted: false }, description: 'Stores DICOM metadata and sync status', indexes: ['seriesUid', 'studyUid', 'storeUid', 'sopInstanceUID', 'syncStatus'], primaryKey: 'id', properties: { createdAt: { type: 'integer' }, id: { maxLength: 300, type: 'string' }, instanceNumber: { default: 0, type: 'integer' }, metadata: { additionalProperties: true, type: 'object' }, seriesUid: { maxLength: 128, type: 'string' }, sopInstanceUID: { maxLength: 128, type: 'string' }, storeUid: { maxLength: 128, type: 'string' }, studyUid: { maxLength: 128, type: 'string' }, syncStatus: { enum: [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.RxDBSyncStatus.LOCAL, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.RxDBSyncStatus.UPLOADING, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.RxDBSyncStatus.SYNCED], maxLength: 16, type: 'string' } }, required: ['id', 'sopInstanceUID', 'seriesUid', 'studyUid', 'storeUid', 'syncStatus', 'instanceNumber'], title: 'Dicom instance schema', type: 'object', version: 2 }; const _schemaTyped = (0,rxdb__WEBPACK_IMPORTED_MODULE_0__.toTypedRxJsonSchema)(dicomSchemaLiteral); const dicomSchema = dicomSchemaLiteral; /***/ }, /***/ 31095 /*!***************************************************************************!*\ !*** ./libs/contracts/src/lib/ot-payload/annotation-payload-v1.schema.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationPayloadV1Schema: () => (/* binding */ annotationPayloadV1Schema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _work_session_annotation_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../work-session/annotation.schema */ 45254); /* harmony import */ var _work_session_common_schema__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../work-session/common.schema */ 17990); /* harmony import */ var _work_session_render_settings_schema__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../work-session/render-settings.schema */ 94881); /* harmony import */ var _annotation_protocol_binding_schema__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./annotation-protocol-binding.schema */ 25727); /** * Window/level rendering parameters shared by all 2D volume modes (axial, sagittal, coronal - * there's no per-mode setting, one preset applies across all of them). Optional and additive: * files exported before this section existed simply lack it, and readers must treat that as * "nothing to apply" rather than an error - see annotation-payload.schema.ts for why this * doesn't warrant a version bump. */ const renderSettings2DSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ selectedWindowPresetName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), windowPresets: zod__WEBPACK_IMPORTED_MODULE_0__.array(_work_session_render_settings_schema__WEBPACK_IMPORTED_MODULE_4__.windowPresetSchema) }); /** * 3D volume ray-cast rendering parameters (ENDO/FLUOROSCOPIC/MIP/VASCULAR/XRAY presets). * Optional and additive, same rationale as renderSettings2D above. */ const renderSettings3DSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ selectedVolumePresetName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), volumeRenderPresets: zod__WEBPACK_IMPORTED_MODULE_0__.array(_work_session_render_settings_schema__WEBPACK_IMPORTED_MODULE_4__.volumeRenderPresetSchema) }); const taviProtocolFormValuesSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ artifacts: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['none', 'calcium-blooming', 'contrast-related-streaks', 'metal-related-streaks', 'high-noise-level', 'poor-contrast-opacification', 'banding-stitching'])).optional(), comments: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(4000).optional(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['good', 'fair', 'poor']).optional(), phaseUnit: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['percent', 'milliseconds', 'unlabelled']).optional(), phaseValue: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(64).optional(), proceed: zod__WEBPACK_IMPORTED_MODULE_0__.boolean().optional(), proceedReason: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['n1', 'n2', 'n3', 'n4', 'n5']).optional(), variant: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['tricuspid', 'tricommissural-functional-bicuspid', 'bav-type-0', 'bav-type-1-rl', 'bav-type-1-ln', 'bav-type-1-rn', 'bav-type-2', 'unicuspid', 'tav-balloon-expandable', 'tav-self-expanding', 'sav-tissue', 'sav-metallic', 'undetermined']).optional(), volumeIdentifier: zod__WEBPACK_IMPORTED_MODULE_0__.string().min(1).max(256).optional() }); const protocolFormValuesSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ // Accepts any id this protocol has shipped under so previously exported OTs stay readable; // normalized to the canonical id below. protocolId: zod__WEBPACK_IMPORTED_MODULE_0__.string().refine(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.isTaviProtocolId), values: taviProtocolFormValuesSchema }).strict(); const annotationPayloadV1Schema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ annotationProtocolBindings: zod__WEBPACK_IMPORTED_MODULE_0__.array(_annotation_protocol_binding_schema__WEBPACK_IMPORTED_MODULE_5__.annotationProtocolBindingV1Schema), // Cast to Annotation[]: the Zod-inferred object types are structurally mutable whereas // the dtos union members are all Readonly<{...}>. Mutable is assignable to readonly at // runtime — the cast bridges the TypeScript-level gap only. annotations: zod__WEBPACK_IMPORTED_MODULE_0__.array(_work_session_annotation_schema__WEBPACK_IMPORTED_MODULE_2__.annotationSchema).transform(array => array), /** Maps annotationId → rendered spline path points (kept separate from control points). */ calculatedPaths: zod__WEBPACK_IMPORTED_MODULE_0__.record(zod__WEBPACK_IMPORTED_MODULE_0__.string(), zod__WEBPACK_IMPORTED_MODULE_0__.array(_work_session_common_schema__WEBPACK_IMPORTED_MODULE_3__.point3Schema)), // OT payloads only persist the TAVI form. Accept the previously exported // unscoped shape so persisted OTs remain importable, then normalize it. protocolFormValues: zod__WEBPACK_IMPORTED_MODULE_0__.union([protocolFormValuesSchema, taviProtocolFormValuesSchema]).transform(formValues => 'protocolId' in formValues ? { ...formValues, protocolId: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.canonicalProtocolId)(formValues.protocolId) } : { protocolId: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.TAVI_PROTOCOL_ID, values: formValues }).optional(), renderSettings2D: renderSettings2DSchema.optional(), renderSettings3D: renderSettings3DSchema.optional(), sourceInstanceUIDs: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).optional(), sourceSeriesUID: zod__WEBPACK_IMPORTED_MODULE_0__.string().optional(), version: zod__WEBPACK_IMPORTED_MODULE_0__.literal(1) }); /***/ }, /***/ 36379 /*!************************************************************************!*\ !*** ./libs/contracts/src/lib/ot-payload/annotation-payload.schema.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OT_PAYLOAD_LATEST_VERSION: () => (/* binding */ OT_PAYLOAD_LATEST_VERSION), /* harmony export */ OT_PAYLOAD_SCHEMA_VERSION: () => (/* binding */ OT_PAYLOAD_SCHEMA_VERSION), /* harmony export */ annotationPayloadSchema: () => (/* binding */ annotationPayloadSchema), /* harmony export */ annotationPayloadV1Schema: () => (/* reexport safe */ _annotation_payload_v1_schema__WEBPACK_IMPORTED_MODULE_0__.annotationPayloadV1Schema) /* harmony export */ }); /* harmony import */ var _annotation_payload_v1_schema__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-payload-v1.schema */ 31095); /** * Discriminated union over all payload versions, keyed on `version`. * Add new versions here as they are introduced: * * export const annotationPayloadSchema = z.discriminatedUnion('version', [ * annotationPayloadV1Schema, * annotationPayloadV2Schema, * ]); */ const annotationPayloadSchema = _annotation_payload_v1_schema__WEBPACK_IMPORTED_MODULE_0__.annotationPayloadV1Schema; const OT_PAYLOAD_LATEST_VERSION = 1; const OT_PAYLOAD_SCHEMA_VERSION = '1.0.0'; /***/ }, /***/ 25727 /*!*********************************************************************************!*\ !*** ./libs/contracts/src/lib/ot-payload/annotation-protocol-binding.schema.ts ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationProtocolBindingV1Schema: () => (/* binding */ annotationProtocolBindingV1Schema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); const annotationProtocolBindingV1Schema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ annotationId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.string(), color: zod__WEBPACK_IMPORTED_MODULE_0__.string(), placeholderIndex: zod__WEBPACK_IMPORTED_MODULE_0__.number(), placeholderName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), protocolId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), protocolName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), protocolPlaceholderId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), /** JSON-serialized relationship object, or empty string when no relationship. */ role: zod__WEBPACK_IMPORTED_MODULE_0__.string() }); /***/ }, /***/ 16520 /*!****************************************************!*\ !*** ./libs/contracts/src/lib/ot-payload/index.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OT_PAYLOAD_LATEST_VERSION: () => (/* reexport safe */ _annotation_payload_schema__WEBPACK_IMPORTED_MODULE_0__.OT_PAYLOAD_LATEST_VERSION), /* harmony export */ OT_PAYLOAD_SCHEMA_VERSION: () => (/* reexport safe */ _annotation_payload_schema__WEBPACK_IMPORTED_MODULE_0__.OT_PAYLOAD_SCHEMA_VERSION), /* harmony export */ annotationPayloadSchema: () => (/* reexport safe */ _annotation_payload_schema__WEBPACK_IMPORTED_MODULE_0__.annotationPayloadSchema), /* harmony export */ annotationPayloadV1Schema: () => (/* reexport safe */ _annotation_payload_schema__WEBPACK_IMPORTED_MODULE_0__.annotationPayloadV1Schema), /* harmony export */ annotationProtocolBindingV1Schema: () => (/* reexport safe */ _annotation_protocol_binding_schema__WEBPACK_IMPORTED_MODULE_2__.annotationProtocolBindingV1Schema) /* harmony export */ }); /* harmony import */ var _annotation_payload_schema__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-payload.schema */ 36379); /* harmony import */ var _annotation_payload_v1_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./annotation-payload-v1.schema */ 31095); /* harmony import */ var _annotation_protocol_binding_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotation-protocol-binding.schema */ 25727); /***/ }, /***/ 10706 /*!******************************************************!*\ !*** ./libs/contracts/src/lib/utils/schema-utils.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ fixTuplesForDraft7: () => (/* binding */ fixTuplesForDraft7) /* harmony export */ }); /* eslint-disable sonarjs/cyclomatic-complexity */ /* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Iterate through a JSON Schema instance and convert any Tuple types to a format * that RxDB can parse. We originally tried calling `z.toJSONSchema()` as `draft-7` but * this also caused problems. */ function fixTuplesForDraft7(schema) { if (typeof schema !== 'object' || schema === null) return schema; const result = { ...schema }; // Convert prefixItems -> Draft 7 tuple form if (result['prefixItems']) { const tupleLength = result['prefixItems'].length; result['items'] = result['prefixItems'].map(s => fixTuplesForDraft7(s)); delete result['prefixItems']; result['minItems'] = result['minItems'] ?? tupleLength; result['maxItems'] = result['maxItems'] ?? tupleLength; result['additionalItems'] = false; } // Recurse into items — must handle both array and object forms if (Array.isArray(result['items'])) { result['items'] = result['items'].map(item => fixTuplesForDraft7(item)); } else if (result['items'] !== null && typeof result['items'] === 'object') { result['items'] = fixTuplesForDraft7(result['items']); } else { // Nothing needed } // Recurse into all composition keywords for (const key of ['oneOf', 'anyOf', 'allOf']) { if (Array.isArray(result[key])) { result[key] = result[key].map(item => fixTuplesForDraft7(item)); } } // Recurse into single-schema keywords for (const key of ['additionalProperties', 'additionalItems', 'contains', 'not', 'if', 'then', 'else']) { if (result[key] !== null && typeof result[key] === 'object') { result[key] = fixTuplesForDraft7(result[key]); } } // Recurse into map-of-schemas keywords for (const key of ['properties', 'patternProperties', '$defs', 'definitions']) { if (result[key] !== null && typeof result[key] === 'object') { result[key] = Object.fromEntries(Object.entries(result[key]).map(([k, v]) => [k, fixTuplesForDraft7(v)])); } } return result; } /***/ }, /***/ 45254 /*!******************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/annotation.schema.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationSchema: () => (/* binding */ annotationSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _common_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./common.schema */ 17990); const base = zod__WEBPACK_IMPORTED_MODULE_0__.object({ color: zod__WEBPACK_IMPORTED_MODULE_0__.string(), displayOrder: zod__WEBPACK_IMPORTED_MODULE_0__.number().nonnegative().default(0), hidden: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), id: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string(), placeholderId: zod__WEBPACK_IMPORTED_MODULE_0__.string().optional() }); const point = base.extend({ position: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.string()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['attached-point', 'curvature-point']) }).optional(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT) }); const angle = base.extend({ points: zod__WEBPACK_IMPORTED_MODULE_0__.array(_common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema).length(3), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.string(), zod__WEBPACK_IMPORTED_MODULE_0__.string()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['angle-between-spline-axes', 'angle-between-splines']) }).optional(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE) }); const cylinder = base.extend({ diameter: zod__WEBPACK_IMPORTED_MODULE_0__.number(), height: zod__WEBPACK_IMPORTED_MODULE_0__.number(), locked: zod__WEBPACK_IMPORTED_MODULE_0__.boolean().default(false), orientation: _common_schema__WEBPACK_IMPORTED_MODULE_2__.quatSchema, position: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, sides: zod__WEBPACK_IMPORTED_MODULE_0__.number(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CYLINDER) }); const distance = base.extend({ points: zod__WEBPACK_IMPORTED_MODULE_0__.array(_common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema).length(2), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.union([zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.string()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['attached-distance', 'center-distance', 'chord', 'closest-distance-to-one-annotation', 'projected-distance']) }), zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.string(), zod__WEBPACK_IMPORTED_MODULE_0__.string()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['angle-between-spline-axes', 'angle-between-splines', 'closest-distance-between-annotations', 'distance-between', 'projected-distance-from-point']) })]).optional(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE) }); const hollowCylinder = base.extend({ height: zod__WEBPACK_IMPORTED_MODULE_0__.number(), innerDiameter: zod__WEBPACK_IMPORTED_MODULE_0__.number(), locked: zod__WEBPACK_IMPORTED_MODULE_0__.boolean().default(false), orientation: _common_schema__WEBPACK_IMPORTED_MODULE_2__.quatSchema, outerDiameter: zod__WEBPACK_IMPORTED_MODULE_0__.number(), position: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, sides: zod__WEBPACK_IMPORTED_MODULE_0__.number(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.HOLLOW_CYLINDER) }); const openSpline = base.extend({ points: zod__WEBPACK_IMPORTED_MODULE_0__.array(_common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema).min(2), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.string()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal('attached-spline') }).optional(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE) }); const closedSpline = base.extend({ points: zod__WEBPACK_IMPORTED_MODULE_0__.array(_common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema).min(2), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE) }); const stl = base.extend({ autoAlignAxis: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), axisOfSymmetryRotation: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.number()), centerOfRotation: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema.optional(), fileName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), geometryId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), locked: zod__WEBPACK_IMPORTED_MODULE_0__.boolean().default(false), orientation: _common_schema__WEBPACK_IMPORTED_MODULE_2__.quatSchema, position: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, type: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.STL) }); const annotationSchema = zod__WEBPACK_IMPORTED_MODULE_0__.discriminatedUnion('type', [angle, closedSpline, cylinder, distance, hollowCylinder, openSpline, point, stl]); /***/ }, /***/ 44876 /*!**************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/chamber.chema.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ chamberSchema: () => (/* binding */ chamberSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 99756); /* harmony import */ var _common_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common.schema */ 17990); const chamberSchema = zod__WEBPACK_IMPORTED_MODULE_0__["default"].object({ ax: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number(), cameraOrientation: zod__WEBPACK_IMPORTED_MODULE_0__["default"].object({ ax: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number(), cc: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number(), rl: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number() }), color: zod__WEBPACK_IMPORTED_MODULE_0__["default"].string(), crosshairRotation: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number().optional(), hidden: zod__WEBPACK_IMPORTED_MODULE_0__["default"].boolean(), id: zod__WEBPACK_IMPORTED_MODULE_0__["default"].uuid(), intersection: _common_schema__WEBPACK_IMPORTED_MODULE_1__.point3Schema.optional(), isocenter: _common_schema__WEBPACK_IMPORTED_MODULE_1__.point3Schema.optional(), isPosterior: zod__WEBPACK_IMPORTED_MODULE_0__["default"].boolean(), name: zod__WEBPACK_IMPORTED_MODULE_0__["default"].string() }); /***/ }, /***/ 17990 /*!**************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/common.schema.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ matrixSchema: () => (/* binding */ matrixSchema), /* harmony export */ point2Schema: () => (/* binding */ point2Schema), /* harmony export */ point3Schema: () => (/* binding */ point3Schema), /* harmony export */ quatSchema: () => (/* binding */ quatSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); const point2Schema = zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number()]).readonly(); const point3Schema = zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number()]).readonly(); const matrixSchema = zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.number()).length(9); const quatSchema = zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number(), zod__WEBPACK_IMPORTED_MODULE_0__.number()]).readonly(); /***/ }, /***/ 32656 /*!******************************************************!*\ !*** ./libs/contracts/src/lib/work-session/index.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WORK_SESSION_LATEST_SCHEMA: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.WORK_SESSION_LATEST_SCHEMA), /* harmony export */ annotationSchema: () => (/* reexport safe */ _annotation_schema__WEBPACK_IMPORTED_MODULE_0__.annotationSchema), /* harmony export */ matrixSchema: () => (/* reexport safe */ _common_schema__WEBPACK_IMPORTED_MODULE_1__.matrixSchema), /* harmony export */ placeholderSchema: () => (/* reexport safe */ _placeholder_schema__WEBPACK_IMPORTED_MODULE_2__.placeholderSchema), /* harmony export */ point2Schema: () => (/* reexport safe */ _common_schema__WEBPACK_IMPORTED_MODULE_1__.point2Schema), /* harmony export */ point3Schema: () => (/* reexport safe */ _common_schema__WEBPACK_IMPORTED_MODULE_1__.point3Schema), /* harmony export */ protocolDefinitionSchema: () => (/* reexport safe */ _protocol_schema__WEBPACK_IMPORTED_MODULE_3__.protocolDefinitionSchema), /* harmony export */ protocolInstanceSchema: () => (/* reexport safe */ _protocol_schema__WEBPACK_IMPORTED_MODULE_3__.protocolInstanceSchema), /* harmony export */ protocolVolumeDataSchema: () => (/* reexport safe */ _protocol_schema__WEBPACK_IMPORTED_MODULE_3__.protocolVolumeDataSchema), /* harmony export */ quatSchema: () => (/* reexport safe */ _common_schema__WEBPACK_IMPORTED_MODULE_1__.quatSchema), /* harmony export */ rxDbAttachmentSchema: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.rxDbAttachmentSchema), /* harmony export */ workSessionJsonSchema: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.workSessionJsonSchema), /* harmony export */ workSessionRxdbJsonSchema: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.workSessionRxdbJsonSchema), /* harmony export */ workSessionSchema: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.workSessionSchema), /* harmony export */ workSessionSchemaWithAttachments: () => (/* reexport safe */ _work_session_schema__WEBPACK_IMPORTED_MODULE_4__.workSessionSchemaWithAttachments) /* harmony export */ }); /* harmony import */ var _annotation_schema__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation.schema */ 45254); /* harmony import */ var _common_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common.schema */ 17990); /* harmony import */ var _placeholder_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./placeholder.schema */ 1516); /* harmony import */ var _protocol_schema__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./protocol.schema */ 16653); /* harmony import */ var _work_session_schema__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./work-session.schema */ 87969); /***/ }, /***/ 1516 /*!*******************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/placeholder.schema.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ placeholderSchema: () => (/* binding */ placeholderSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const placeholderBase = zod__WEBPACK_IMPORTED_MODULE_0__.object({ color: zod__WEBPACK_IMPORTED_MODULE_0__.string(), id: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string() }); const point = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).length(1), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['attached-point', 'curvature-point']) }).optional() }); const angle = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).length(2), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['angle-between-spline-axes', 'angle-between-splines']) }).optional() }); const cylinder = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CYLINDER) }); const distance = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.union([zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).length(1), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['attached-distance', 'center-distance', 'chord', 'closest-distance-to-one-annotation', 'projected-distance']) }), zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).length(2), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['angle-between-spline-axes', 'angle-between-splines', 'closest-distance-between-annotations', 'distance-between', 'projected-distance-from-point']) })]).optional() }); const hollowCylinder = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.HOLLOW_CYLINDER) }); const openSpline = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE), relationship: zod__WEBPACK_IMPORTED_MODULE_0__.object({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()).length(1), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal('attached-spline') }).optional() }); const closedSpline = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE) }); const stl = placeholderBase.extend({ annotationType: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.STL) }); const placeholderSchema = zod__WEBPACK_IMPORTED_MODULE_0__.discriminatedUnion('annotationType', [angle, closedSpline, cylinder, distance, hollowCylinder, openSpline, point, stl]); /***/ }, /***/ 16653 /*!****************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/protocol.schema.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ protocolDefinitionSchema: () => (/* binding */ protocolDefinitionSchema), /* harmony export */ protocolInstanceSchema: () => (/* binding */ protocolInstanceSchema), /* harmony export */ protocolVolumeDataSchema: () => (/* binding */ protocolVolumeDataSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _placeholder_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./placeholder.schema */ 1516); const formFieldValueSchema = zod__WEBPACK_IMPORTED_MODULE_0__.union([zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), zod__WEBPACK_IMPORTED_MODULE_0__.string(), zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.boolean()), zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string())]).readonly(); const validationRuleSchema = zod__WEBPACK_IMPORTED_MODULE_0__.looseObject({ type: zod__WEBPACK_IMPORTED_MODULE_0__.string() }).readonly(); const protocolFormFieldSchema = zod__WEBPACK_IMPORTED_MODULE_0__.looseObject({ representation: zod__WEBPACK_IMPORTED_MODULE_0__.string(), valueType: zod__WEBPACK_IMPORTED_MODULE_0__.string() }).readonly(); const protocolFormDefinitionSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ canProceedRule: validationRuleSchema.optional(), fields: zod__WEBPACK_IMPORTED_MODULE_0__.array(protocolFormFieldSchema), name: zod__WEBPACK_IMPORTED_MODULE_0__.string(), required: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), validation: zod__WEBPACK_IMPORTED_MODULE_0__.record(zod__WEBPACK_IMPORTED_MODULE_0__.string(), validationRuleSchema) }).readonly(); const protocolDefinitionSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ form: protocolFormDefinitionSchema.optional(), id: zod__WEBPACK_IMPORTED_MODULE_0__.string(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string(), placeholders: zod__WEBPACK_IMPORTED_MODULE_0__.array(_placeholder_schema__WEBPACK_IMPORTED_MODULE_1__.placeholderSchema).readonly() }).readonly(); const protocolInstanceSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ formValues: zod__WEBPACK_IMPORTED_MODULE_0__.record(zod__WEBPACK_IMPORTED_MODULE_0__.string(), formFieldValueSchema).readonly().optional(), placeholderMappings: zod__WEBPACK_IMPORTED_MODULE_0__.record(zod__WEBPACK_IMPORTED_MODULE_0__.string(), zod__WEBPACK_IMPORTED_MODULE_0__.string()).readonly(), protocolId: zod__WEBPACK_IMPORTED_MODULE_0__.string() }).readonly(); // Used at volume-level const protocolVolumeDataSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ activeProtocolId: zod__WEBPACK_IMPORTED_MODULE_0__.string().optional(), instances: zod__WEBPACK_IMPORTED_MODULE_0__.array(protocolInstanceSchema) }); /***/ }, /***/ 94881 /*!***********************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/render-settings.schema.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ renderSettingsStoreStateSchema: () => (/* binding */ renderSettingsStoreStateSchema), /* harmony export */ volumeRenderPresetSchema: () => (/* binding */ volumeRenderPresetSchema), /* harmony export */ windowPresetSchema: () => (/* binding */ windowPresetSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const endoPreset = zod__WEBPACK_IMPORTED_MODULE_0__.object({ airTissueThreshold: zod__WEBPACK_IMPORTED_MODULE_0__.number(), ambient: zod__WEBPACK_IMPORTED_MODULE_0__.number(), bloodCalciumThreshold: zod__WEBPACK_IMPORTED_MODULE_0__.number(), diffuse: zod__WEBPACK_IMPORTED_MODULE_0__.number(), distalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__.number(), label: zod__WEBPACK_IMPORTED_MODULE_0__.string(), opacityTransitionWidth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), proximalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), rgbTransitionWidth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedPreset: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.ENDO), specular: zod__WEBPACK_IMPORTED_MODULE_0__.number(), specularPower: zod__WEBPACK_IMPORTED_MODULE_0__.number(), tissueBloodThreshold: zod__WEBPACK_IMPORTED_MODULE_0__.number() }); const fluoroscopicPreset = zod__WEBPACK_IMPORTED_MODULE_0__.object({ brightness: zod__WEBPACK_IMPORTED_MODULE_0__.number(), distalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__.number(), label: zod__WEBPACK_IMPORTED_MODULE_0__.string(), proximalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedPreset: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.FLUOROSCOPIC), threshold: zod__WEBPACK_IMPORTED_MODULE_0__.number() }); // NOTE: no `.default()` on any field here — RxDB's SchemaCheck (SC7) rejects default // values on anything nested under an array item / discriminated-union branch; they're // only legal at the schema's top level. Defaults for these fields are supplied // explicitly instead, by VOLUME_RENDERING_PRESETS (new sessions) and the work-session // migrations (backfilling old ones) — see v13, v20, and v26. const mipPreset = zod__WEBPACK_IMPORTED_MODULE_0__.object({ // brightness = window level, threshold = window width - see MipSettings. brightness: zod__WEBPACK_IMPORTED_MODULE_0__.number(), distalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__.number(), label: zod__WEBPACK_IMPORTED_MODULE_0__.string(), proximalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedPreset: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.MIP), threshold: zod__WEBPACK_IMPORTED_MODULE_0__.number() }); const vascularPreset = zod__WEBPACK_IMPORTED_MODULE_0__.object({ ambient: zod__WEBPACK_IMPORTED_MODULE_0__.number(), bloodCalciumThreshold: zod__WEBPACK_IMPORTED_MODULE_0__.number(), clusterSize: zod__WEBPACK_IMPORTED_MODULE_0__.number(), diffuse: zod__WEBPACK_IMPORTED_MODULE_0__.number(), distalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), erosionRadius: zod__WEBPACK_IMPORTED_MODULE_0__.number(), gridStep: zod__WEBPACK_IMPORTED_MODULE_0__.number(), hasAcceptedSegmentation: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__.number(), label: zod__WEBPACK_IMPORTED_MODULE_0__.string(), maxHU: zod__WEBPACK_IMPORTED_MODULE_0__.number(), minHU: zod__WEBPACK_IMPORTED_MODULE_0__.number(), opacityTransitionWidth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), outlierOpacity: zod__WEBPACK_IMPORTED_MODULE_0__.number(), proximalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedPreset: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.VASCULAR), specular: zod__WEBPACK_IMPORTED_MODULE_0__.number(), specularPower: zod__WEBPACK_IMPORTED_MODULE_0__.number(), tissueBloodThreshold: zod__WEBPACK_IMPORTED_MODULE_0__.number(), vascularSegmentationState: zod__WEBPACK_IMPORTED_MODULE_0__.nativeEnum(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VascularSegmentationState), vascularThresholdsAutoTuned: zod__WEBPACK_IMPORTED_MODULE_0__.boolean() }); const xrayPreset = zod__WEBPACK_IMPORTED_MODULE_0__.object({ brightness: zod__WEBPACK_IMPORTED_MODULE_0__.number(), distalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), imageQuality: zod__WEBPACK_IMPORTED_MODULE_0__.number(), label: zod__WEBPACK_IMPORTED_MODULE_0__.string(), proximalDepth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedPreset: zod__WEBPACK_IMPORTED_MODULE_0__.literal(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.XRAY), threshold: zod__WEBPACK_IMPORTED_MODULE_0__.number() }); const legacyVolumeRenderingPresetNameMap = { ENDO: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.ENDO, Endovascular: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.ENDO, FLUOROSCOPIC: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.FLUOROSCOPIC, Fluoroscopic: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.FLUOROSCOPIC, 'X-Ray': _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.XRAY, XRAY: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption.XRAY }; const normalizeVolumeRenderingPresetName = value => { if (typeof value !== 'string') return; return Object.values(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.VolumeRenderingOption).find(option => option === value) ?? legacyVolumeRenderingPresetNameMap[value]; }; const normalizeVolumeRenderPreset = value => { if (!value || typeof value !== 'object' || Array.isArray(value)) return value; const preset = value; const normalizedPreset = normalizeVolumeRenderingPresetName(preset['selectedPreset']) ?? normalizeVolumeRenderingPresetName(preset['value']); if (!normalizedPreset) return value; return { ...preset, selectedPreset: normalizedPreset }; }; const volumeRenderPresetSchema = zod__WEBPACK_IMPORTED_MODULE_0__.preprocess(normalizeVolumeRenderPreset, zod__WEBPACK_IMPORTED_MODULE_0__.discriminatedUnion('selectedPreset', [endoPreset, fluoroscopicPreset, mipPreset, vascularPreset, xrayPreset])); const windowPresetSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ level: zod__WEBPACK_IMPORTED_MODULE_0__.number(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string(), width: zod__WEBPACK_IMPORTED_MODULE_0__.number() }); const renderSettingsStoreStateSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ sCurveGraphFontSize: zod__WEBPACK_IMPORTED_MODULE_0__.number(), sCurveLineWidth: zod__WEBPACK_IMPORTED_MODULE_0__.number(), selectedVolumePresetName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), selectedWindowPresetName: zod__WEBPACK_IMPORTED_MODULE_0__.string(), volumeRenderPresets: zod__WEBPACK_IMPORTED_MODULE_0__.array(volumeRenderPresetSchema), windowPresets: zod__WEBPACK_IMPORTED_MODULE_0__.array(windowPresetSchema) }); /***/ }, /***/ 35354 /*!***************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/s-curve.schema.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurveRelativeMeasurementSchema: () => (/* binding */ sCurveRelativeMeasurementSchema), /* harmony export */ sCurveSchema: () => (/* binding */ sCurveSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _common_schema__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common.schema */ 17990); const sCurveBase = zod__WEBPACK_IMPORTED_MODULE_0__.object({ color: zod__WEBPACK_IMPORTED_MODULE_0__.string(), hidden: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), id: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string() }); const controlPointSCurve = sCurveBase.extend({ controlPoints: zod__WEBPACK_IMPORTED_MODULE_0__.array(_common_schema__WEBPACK_IMPORTED_MODULE_1__.point2Schema), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal('control-point') }); // Spline-derived s-curves are re-synced live from the annotation store on load, so // only a lightweight stub (preserving id/hidden/ordering) is persisted in // their place - never the full embedded spline. const sCurveStub = zod__WEBPACK_IMPORTED_MODULE_0__.object({ hidden: zod__WEBPACK_IMPORTED_MODULE_0__.boolean(), id: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), type: zod__WEBPACK_IMPORTED_MODULE_0__.literal('stub') }); const sCurveSchema = zod__WEBPACK_IMPORTED_MODULE_0__.discriminatedUnion('type', [controlPointSCurve, sCurveStub]); // The angle/intersection VALUE is never persisted - always derived live from the // current shape of the source curves. Only the measurement's own identity/display // fields (which curves it relates, name/color/visibility) are persisted here. const sCurveRelativeMeasurementSchema = sCurveBase.extend({ sourceIds: zod__WEBPACK_IMPORTED_MODULE_0__.tuple([zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), zod__WEBPACK_IMPORTED_MODULE_0__.uuid()]).readonly(), type: zod__WEBPACK_IMPORTED_MODULE_0__["enum"](['angle', 'intersection']) }); /***/ }, /***/ 92603 /*!**********************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/viewport-store.schema.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ viewportStoreStateSchema: () => (/* binding */ viewportStoreStateSchema) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 99756); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _common_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./common.schema */ 17990); const viewportStoreStateSchema = zod__WEBPACK_IMPORTED_MODULE_0__["default"].object({ ax: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number(), cameraDistance: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number(), intersection: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, isocenter: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema, isPosterior: zod__WEBPACK_IMPORTED_MODULE_0__["default"].boolean(), matrix: _common_schema__WEBPACK_IMPORTED_MODULE_2__.matrixSchema, showCrosshairs: zod__WEBPACK_IMPORTED_MODULE_0__["default"].boolean(), // NOTE: Using `z.enum(ViewportAxisState)` as the key breaks the RxDB schema viewportAxisMapping: zod__WEBPACK_IMPORTED_MODULE_0__["default"].record(zod__WEBPACK_IMPORTED_MODULE_0__["default"].string(), zod__WEBPACK_IMPORTED_MODULE_0__["default"]["enum"](_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.ViewportAxis)), volumeCenter: _common_schema__WEBPACK_IMPORTED_MODULE_2__.point3Schema.optional(), zoom: zod__WEBPACK_IMPORTED_MODULE_0__["default"].number() }); /***/ }, /***/ 87969 /*!********************************************************************!*\ !*** ./libs/contracts/src/lib/work-session/work-session.schema.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WORK_SESSION_LATEST_SCHEMA: () => (/* binding */ WORK_SESSION_LATEST_SCHEMA), /* harmony export */ rxDbAttachmentSchema: () => (/* binding */ rxDbAttachmentSchema), /* harmony export */ workSessionJsonSchema: () => (/* binding */ workSessionJsonSchema), /* harmony export */ workSessionRxdbJsonSchema: () => (/* binding */ workSessionRxdbJsonSchema), /* harmony export */ workSessionSchema: () => (/* binding */ workSessionSchema), /* harmony export */ workSessionSchemaWithAttachments: () => (/* binding */ workSessionSchemaWithAttachments) /* harmony export */ }); /* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zod */ 14713); /* harmony import */ var _utils_schema_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/schema-utils */ 10706); /* harmony import */ var _annotation_schema__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotation.schema */ 45254); /* harmony import */ var _chamber_chema__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./chamber.chema */ 44876); /* harmony import */ var _protocol_schema__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./protocol.schema */ 16653); /* harmony import */ var _render_settings_schema__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./render-settings.schema */ 94881); /* harmony import */ var _s_curve_schema__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./s-curve.schema */ 35354); /* harmony import */ var _viewport_store_schema__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./viewport-store.schema */ 92603); const phaseSelectionSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ activePhaseId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), availablePhaseIds: zod__WEBPACK_IMPORTED_MODULE_0__.array(zod__WEBPACK_IMPORTED_MODULE_0__.string()) }); const volumeBundleSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ annotations: zod__WEBPACK_IMPORTED_MODULE_0__.array(_annotation_schema__WEBPACK_IMPORTED_MODULE_2__.annotationSchema), chambers: zod__WEBPACK_IMPORTED_MODULE_0__.array(_chamber_chema__WEBPACK_IMPORTED_MODULE_3__.chamberSchema), phaseId: zod__WEBPACK_IMPORTED_MODULE_0__.string(), protocolData: _protocol_schema__WEBPACK_IMPORTED_MODULE_4__.protocolVolumeDataSchema, renderSettings: _render_settings_schema__WEBPACK_IMPORTED_MODULE_5__.renderSettingsStoreStateSchema, sCurveRelativeMeasurements: zod__WEBPACK_IMPORTED_MODULE_0__.array(_s_curve_schema__WEBPACK_IMPORTED_MODULE_6__.sCurveRelativeMeasurementSchema), sCurves: zod__WEBPACK_IMPORTED_MODULE_0__.array(_s_curve_schema__WEBPACK_IMPORTED_MODULE_6__.sCurveSchema), viewportCamera: _viewport_store_schema__WEBPACK_IMPORTED_MODULE_7__.viewportStoreStateSchema }); const workSessionSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ annotationSize: zod__WEBPACK_IMPORTED_MODULE_0__.number().default(2), createdAt: zod__WEBPACK_IMPORTED_MODULE_0__.iso.datetime(), createdByUid: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), name: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(64), phaseSelection: phaseSelectionSchema.optional(), protocolDefinitions: zod__WEBPACK_IMPORTED_MODULE_0__.array(_protocol_schema__WEBPACK_IMPORTED_MODULE_4__.protocolDefinitionSchema), renderSettings: _render_settings_schema__WEBPACK_IMPORTED_MODULE_5__.renderSettingsStoreStateSchema, schemaVersion: zod__WEBPACK_IMPORTED_MODULE_0__.number(), seriesUid: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(128), storeUid: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(128), studyUid: zod__WEBPACK_IMPORTED_MODULE_0__.string().max(128), uid: zod__WEBPACK_IMPORTED_MODULE_0__.uuid().length(36), updatedAt: zod__WEBPACK_IMPORTED_MODULE_0__.iso.datetime().min(0).max(2000), updatedByUid: zod__WEBPACK_IMPORTED_MODULE_0__.uuid(), version: zod__WEBPACK_IMPORTED_MODULE_0__.number().min(0).max(Number.MAX_VALUE).default(0), viewportCamera: _viewport_store_schema__WEBPACK_IMPORTED_MODULE_7__.viewportStoreStateSchema, volumes: zod__WEBPACK_IMPORTED_MODULE_0__.array(volumeBundleSchema).default([]) }).refine(data => data.volumes.every(({ annotations }) => new Set(annotations.map(({ displayOrder }) => displayOrder)).size === annotations.length), { message: 'Unique displayOrder required', path: ['volumes'] }); // eslint-disable-next-line unicorn/prevent-abbreviations const rxDbAttachmentSchema = zod__WEBPACK_IMPORTED_MODULE_0__.object({ data: zod__WEBPACK_IMPORTED_MODULE_0__.string().optional(), digest: zod__WEBPACK_IMPORTED_MODULE_0__.string(), length: zod__WEBPACK_IMPORTED_MODULE_0__.number().int(), type: zod__WEBPACK_IMPORTED_MODULE_0__.string() }); const workSessionSchemaWithAttachments = workSessionSchema.extend({ _attachments: zod__WEBPACK_IMPORTED_MODULE_0__.record(zod__WEBPACK_IMPORTED_MODULE_0__.string(), rxDbAttachmentSchema).default({}) }); // NOTE: We use `draft-7` otherwise `z.tuple()` is unsupported by RxDB const workSessionJsonSchema = (0,_utils_schema_utils__WEBPACK_IMPORTED_MODULE_1__.fixTuplesForDraft7)(zod__WEBPACK_IMPORTED_MODULE_0__.toJSONSchema(workSessionSchema)); const properties = workSessionJsonSchema['properties']; const WORK_SESSION_LATEST_SCHEMA = 27; const workSessionRxdbJsonSchema = { attachments: { encrypted: false }, indexes: ['studyUid', 'seriesUid', 'version', 'updatedAt'], primaryKey: 'uid', properties: { ...properties, version: { ...properties.version, multipleOf: 1 } }, required: workSessionJsonSchema['required'], title: 'Work Session Schema', type: 'object', version: WORK_SESSION_LATEST_SCHEMA }; /***/ }, /***/ 42541 /*!***************************************!*\ !*** ./libs/data-access/src/index.ts ***! \***************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AppInitService: () => (/* reexport safe */ _lib_services_app_init_service__WEBPACK_IMPORTED_MODULE_2__.AppInitService), /* harmony export */ AuthInterceptor: () => (/* reexport safe */ _lib_services_auth_interceptor_service__WEBPACK_IMPORTED_MODULE_1__.AuthInterceptor), /* harmony export */ AuthService: () => (/* reexport safe */ _lib_services_auth_service__WEBPACK_IMPORTED_MODULE_0__.AuthService), /* harmony export */ ClientStudySearchProvider: () => (/* reexport safe */ _lib_services_dicom_study_search_provider__WEBPACK_IMPORTED_MODULE_4__.ClientStudySearchProvider), /* harmony export */ DevelopmentOptionsService: () => (/* reexport safe */ _lib_services_dev_options_service__WEBPACK_IMPORTED_MODULE_18__.DevelopmentOptionsService), /* harmony export */ DicomApiService: () => (/* reexport safe */ _lib_services_dicom_dicom_api_service__WEBPACK_IMPORTED_MODULE_3__.DicomApiService), /* harmony export */ DicomDatabaseService: () => (/* reexport safe */ _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__.DicomDatabaseService), /* harmony export */ DicomImportService: () => (/* reexport safe */ _lib_services_dicom_dicom_import_service__WEBPACK_IMPORTED_MODULE_15__.DicomImportService), /* harmony export */ DicomStoreListService: () => (/* reexport safe */ _lib_services_dicom_dicom_store_list_service__WEBPACK_IMPORTED_MODULE_5__.DicomStoreListService), /* harmony export */ PreferencesService: () => (/* reexport safe */ _lib_services_preferences_preferences_service__WEBPACK_IMPORTED_MODULE_16__.PreferencesService), /* harmony export */ RXDB_CONFIG: () => (/* reexport safe */ _lib_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_12__.RXDB_CONFIG), /* harmony export */ RXDB_DEFAULT_STORAGE: () => (/* reexport safe */ _lib_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_12__.RXDB_DEFAULT_STORAGE), /* harmony export */ RecentWorkSessionsService: () => (/* reexport safe */ _lib_services_recent_work_sessions_service__WEBPACK_IMPORTED_MODULE_17__.RecentWorkSessionsService), /* harmony export */ RenderingEngineService: () => (/* reexport safe */ _lib_services_dicom_rendering_engine_service__WEBPACK_IMPORTED_MODULE_6__.RenderingEngineService), /* harmony export */ RxdbManager: () => (/* reexport safe */ _lib_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_12__.RxdbManager), /* harmony export */ StudySearchProvider: () => (/* reexport safe */ _lib_services_dicom_study_search_provider__WEBPACK_IMPORTED_MODULE_4__.StudySearchProvider), /* harmony export */ VolumeLoaderService: () => (/* reexport safe */ _lib_services_dicom_volume_loader_service__WEBPACK_IMPORTED_MODULE_7__.VolumeLoaderService), /* harmony export */ WorkSessionApiService: () => (/* reexport safe */ _lib_services_work_session_work_session_api_service__WEBPACK_IMPORTED_MODULE_8__.WorkSessionApiService), /* harmony export */ WorkSessionDatabaseService: () => (/* reexport safe */ _lib_db_work_session_work_session_database_service__WEBPACK_IMPORTED_MODULE_14__.WorkSessionDatabaseService), /* harmony export */ WorkSessionNavigationService: () => (/* reexport safe */ _lib_services_work_session_work_session_navigation_service__WEBPACK_IMPORTED_MODULE_9__.WorkSessionNavigationService), /* harmony export */ approvalToReviewStatus: () => (/* reexport safe */ _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__.approvalToReviewStatus), /* harmony export */ authGuard: () => (/* reexport safe */ _lib_guards_auth_guard__WEBPACK_IMPORTED_MODULE_10__.authGuard), /* harmony export */ batchFilesForUpload: () => (/* reexport safe */ _lib_services_dicom_dicom_api_service__WEBPACK_IMPORTED_MODULE_3__.batchFilesForUpload), /* harmony export */ isSeriesFullyCached: () => (/* reexport safe */ _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__.isSeriesFullyCached), /* harmony export */ parseImageId: () => (/* reexport safe */ _lib_services_dicom_volume_loader_service__WEBPACK_IMPORTED_MODULE_7__.parseImageId), /* harmony export */ resolveSeriesReviewStatus: () => (/* reexport safe */ _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__.resolveSeriesReviewStatus), /* harmony export */ reviewStatusRank: () => (/* reexport safe */ _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__.reviewStatusRank), /* harmony export */ separateSeriesPhases: () => (/* reexport safe */ _lib_services_dicom_volume_loader_service__WEBPACK_IMPORTED_MODULE_7__.separateSeriesPhases), /* harmony export */ sessionCleanupGuard: () => (/* reexport safe */ _lib_guards_session_cleanup_guard__WEBPACK_IMPORTED_MODULE_11__.sessionCleanupGuard) /* harmony export */ }); /* harmony import */ var _lib_services_auth_service__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/services/auth.service */ 52807); /* harmony import */ var _lib_services_auth_interceptor_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/services/auth-interceptor.service */ 98765); /* harmony import */ var _lib_services_app_init_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/services/app-init.service */ 44769); /* harmony import */ var _lib_services_dicom_dicom_api_service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/services/dicom/dicom-api.service */ 96269); /* harmony import */ var _lib_services_dicom_study_search_provider__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/services/dicom/study-search.provider */ 75826); /* harmony import */ var _lib_services_dicom_dicom_store_list_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/services/dicom/dicom-store-list.service */ 55643); /* harmony import */ var _lib_services_dicom_rendering_engine_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/services/dicom/rendering-engine.service */ 68453); /* harmony import */ var _lib_services_dicom_volume_loader_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/services/dicom/volume-loader.service */ 79950); /* harmony import */ var _lib_services_work_session_work_session_api_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/services/work-session/work-session-api.service */ 29039); /* harmony import */ var _lib_services_work_session_work_session_navigation_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/services/work-session/work-session-navigation.service */ 60923); /* harmony import */ var _lib_guards_auth_guard__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/guards/auth.guard */ 89967); /* harmony import */ var _lib_guards_session_cleanup_guard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/guards/session-cleanup.guard */ 5138); /* harmony import */ var _lib_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./lib/db/rxdb-manager.service */ 67189); /* harmony import */ var _lib_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./lib/db/dicom/dicom-database.service */ 30860); /* harmony import */ var _lib_db_work_session_work_session_database_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/db/work-session/work-session-database.service */ 17818); /* harmony import */ var _lib_services_dicom_dicom_import_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./lib/services/dicom/dicom-import.service */ 67430); /* harmony import */ var _lib_services_preferences_preferences_service__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./lib/services/preferences/preferences.service */ 4508); /* harmony import */ var _lib_services_recent_work_sessions_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./lib/services/recent-work-sessions.service */ 23974); /* harmony import */ var _lib_services_dev_options_service__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./lib/services/dev-options.service */ 40911); /***/ }, /***/ 30860 /*!*********************************************************************!*\ !*** ./libs/data-access/src/lib/db/dicom/dicom-database.service.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomDatabaseService: () => (/* binding */ DicomDatabaseService), /* harmony export */ approvalToReviewStatus: () => (/* binding */ approvalToReviewStatus), /* harmony export */ isSeriesFullyCached: () => (/* binding */ isSeriesFullyCached), /* harmony export */ resolveSeriesReviewStatus: () => (/* binding */ resolveSeriesReviewStatus), /* harmony export */ reviewStatusRank: () => (/* reexport safe */ _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_16__.reviewStatusRank) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_awaitAsyncGenerator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/awaitAsyncGenerator.js */ 60256); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_wrapAsyncGenerator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/wrapAsyncGenerator.js */ 8014); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/platform-browser */ 20189); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 87675); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 90015); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var p_limit__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! p-limit */ 13551); /* harmony import */ var p_retry__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! p-retry */ 24214); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @tomoverse/types */ 25575); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _tomoverse_utils_promises__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/utils/promises */ 75379); /* harmony import */ var _rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../../rxdb-attachment-binary */ 94669); /* harmony import */ var _services_dicom_dicom_api_service__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../../services/dicom/dicom-api.service */ 96269); /* harmony import */ var _rxdb_manager_service__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../rxdb-manager.service */ 67189); function isSeriesFullyCached(progress) { return progress.totalCount > 0 && progress.cachedCount >= progress.totalCount; } const PIXEL_DATA_ATTACHMENT_NAME = 'pixelData'; function mergeReviewStatus(a, b) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_16__.reviewStatusRank)(b) > (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_16__.reviewStatusRank)(a) ? b : a; } function approvalToReviewStatus(approval) { switch (approval.trim()) { case 'APPROVED': { return 'approved'; } case 'REJECTED': { return 'rejected'; } case 'UNAPPROVED': { return 'unapproved'; } default: { return 'none'; } } } function readMetaTag(meta, tag) { return String(meta?.[tag]?.Value?.[0] ?? '').trim(); } /** Highest-precedence status across the instances: approved > rejected > unapproved. */ function resolveReviewStatusFromMetas(metas) { let status = 'none'; for (const meta of metas) { // Private mirror fallback in case the store dropped the non-indexed standard tag. const instanceStatus = approvalToReviewStatus(readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.ApprovalStatus) || readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.TvctReviewStatus)); if (instanceStatus === 'approved') return 'approved'; status = mergeReviewStatus(status, instanceStatus); } return status; } function resolveSeriesReviewStatus(instances) { return resolveReviewStatusFromMetas(instances.map(inst => inst.toJSON().metadata)); } const FETCH_CONCURRENCY = 15; // Deliberately much lower than FETCH_CONCURRENCY: peekStudyInstanceCount is a background // enrichment for a heading display, not a critical load path - firing one request per series // unbounded can flood the connection pool and delay unrelated concurrent requests (e.g. the // study-summary peek for just the first series) behind this purely informational sum. const PEEK_CONCURRENCY = 4; const FETCH_RETRIES = 1; const FETCH_MIN_RETRY_TIMEOUT = 500; // A local RxDB write should never legitimately take this long - see fetchOverNetworkAndCache. const SAVE_BINARY_TIMEOUT_MS = 15_000; const SAVE_BINARY_TIMEOUT_PREFIX = 'Timed out saving binary for instance'; /** * Angular's HttpErrorResponse extends HttpResponseBase, not the built-in Error, * so `instanceof Error` returns false. pRetry v7 normalises non-Error throws to a * generic TypeError, losing the .status property that shouldRetry needs to bail * on 404/400. Wrap the function so pRetry always receives a real Error. */ function asRetriable(function_) { return /*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { return yield function_(); } catch (error) { if (error instanceof Error) throw error; const normalizedError = new Error(error && typeof error === 'object' && 'message' in error ? String(error.message) : String(error)); if (error && typeof error === 'object' && 'status' in error) { normalizedError.status = error.status; } throw normalizedError; } }); } class DicomDatabaseService { rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_23__.RxdbManager); api = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_services_dicom_dicom_api_service__WEBPACK_IMPORTED_MODULE_22__.DicomApiService); sanitizer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.DomSanitizer); prefetchProgressBySeriesUid = new Map(); // Cornerstone's own rendering/prefetch machinery can keep re-requesting an image it never // successfully loaded, indefinitely - without this, a single permanently-bad (400/404) // instance turns into an unbounded stream of repeat network requests (observed freezing the // tab from memory pressure on a large series). Scoped per store+instance, in-memory only, so a // page reload gives every instance a clean slate. permanentlyFailedInstances = new Set(); // A series' true instance total never changes once known (deleting the local cache doesn't // change what's on the server) - without this, re-opening the same study re-runs the same // network peek every time, purely to redisplay a number the app already learned. Keyed by // storeUid+seriesUid, in-memory only, so it naturally clears on refresh; clearPeekCache() // clears it on logout too, so the next account doesn't see a previous session's data. peekedSeriesInstanceCountCache = new Map(); // Bumped by clearPeekCache(). A peek already in flight when sign-out fires must not repopulate // the cache it just cleared once its RxDB read or network call resolves - peekSeriesInstanceCount // captures this before awaiting anything and only writes back if it's still current. peekedSeriesInstanceCountCacheGeneration = 0; // The background series-cache prefetch and Cornerstone's own on-demand per-image loading both // route through getBinary and, on a cold cache, race to fetch the SAME instance concurrently - // this dedupes those into a single in-flight request instead of hitting the network twice. inFlightFetches = new Map(); // VolumeLoaderService is provided per-route/per-component (the volume viewer and the imaging // library's series preview each get their own instance), so its own in-flight caching can't see // across instances. In practice that means previewing a series then opening it in the full // viewer starts two independent prefetchInstanceBinaries loops for the same series, each with // its own progress counter and its own pLimit(FETCH_CONCURRENCY) queue - doubling background // fetch load for no benefit. This service is the one thing both instances actually share // (providedIn: 'root'), so dedupe here instead. Scoped by series+store only, not by the // sopInstanceUIDs subset a scoped (phase-limited) caller might pass - a scoped caller piggy- // backing on an in-flight unscoped (whole-series) prefetch is correct; a caller whose specific // subset a differently-scoped in-flight prefetch doesn't fully cover is still safe, since // getBinary's own fetch-on-demand fallback covers whatever this skips. inFlightPrefetches = new Map(); // The single point every network fetch actually goes through, regardless of caller - the // background prefetch and Cornerstone's on-demand per-image loading (via getBinary) used to // each apply their own separate pLimit, which allowed up to ~20 real network requests in flight // at once; now all flows share a single FETCH_CONCURRENCY (15) limiter to cap the true total // and avoid congesting the connection pool (individual fetches were observed taking 6-7s // instead of well under 1s when the connection was saturated). networkFetchLimit = (0,p_limit__WEBPACK_IMPORTED_MODULE_13__["default"])(FETCH_CONCURRENCY); // Nothing else evicts a series' cached instances/attachments once the volume viewer moves on, // so a session that opens many series (e.g. a large scan) grows this store unboundedly, which // measurably slows down every later query against it. Evict by total cached attachment size // rather than by count - one large scan can dwarf several small ones - and base "least // recently used" on RxDB's own persisted last-write-time rather than in-memory session state, // so scans cached in a previous session (before the last page reload) get cleaned up too. static MAX_CACHED_INSTANCE_BYTES = 1024 * 1024 * 1024; // 1 GiB instanceKey(sopInstanceUID, storeUid) { return `${storeUid}:${sopInstanceUID}`; } /** * A concurrent write (e.g. an in-flight background prefetch still saving binaries into this * collection, or a second overlapping caller removing from it - a user's manual clear-cache * landing on top of markSeriesViewed's background eviction) can bump a document's revision * between reading it and removing it here. Plain `.remove()` has no retry of its own and * throws CONFLICT outright on any revision mismatch; a single manual retry against * `getLatest()` isn't enough either, since whatever raced us can keep winning more than once * (confirmed in practice: the retry's own remove() hit a second CONFLICT). * * `incrementalRemove()` routes through RxDB's own incremental write queue instead, which on a * CONFLICT re-fetches the document's actual current state and re-applies the deletion against * it, looping until it wins rather than giving up after a fixed number of attempts - so it * converges no matter how many times a concurrent writer beats us to it. */ removeDocumentWithRetry(document) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!document || document.deleted) return; yield document.incrementalRemove(); })(); } getSeriesForStudy(studyUid, storeUid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this2.rxdbManager.getSeriesCollection(); const localSeries = yield collection.find({ selector: { storeUid, studyInstanceUID: studyUid }, sort: [{ seriesNumber: 'asc' }] }).exec(); if (localSeries.length > 0) { return localSeries.map(series => series.toJSON()); } const remoteSeries = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this2.api.getSeriesForStudy(studyUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); yield _this2.persistSeries(remoteSeries, studyUid, storeUid); return remoteSeries; })(); } streamSeriesForStudy(studyUid, storeUid) { return this.rxdbManager.dicomSeries$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(collection => collection.find({ selector: { storeUid, studyInstanceUID: studyUid }, sort: [{ seriesNumber: 'asc' }] }).$), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(documents => documents.map(({ toJSON }) => toJSON()))); } refreshSeriesForStudy(_x, _x2) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (studyUid, storeUid, shouldPersist = () => true) { const remoteSeries = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this3.api.getSeriesForStudy(studyUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); yield _this3.persistSeries(remoteSeries, studyUid, storeUid, shouldPersist); return remoteSeries; }).apply(this, arguments); } /** * Hard resync used by an explicit "reload" - clears the local series cache so server-side * deletions are picked up, then repopulates it from the store. Fetches BEFORE clearing: if * the network call fails (e.g. while a large scan elsewhere is saturating the connection), * the local cache is left untouched instead of wiped with nothing to replace it - clearing * first turned a transient network failure into a permanently empty study that no amount of * re-triggering "reload" could recover from, since every retry re-cleared before re-fetching. */ resyncSeriesForStudy(studyUid, storeUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const remoteSeries = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this4.api.getSeriesForStudy(studyUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); yield _this4.clearSeriesForStudy(studyUid, storeUid); yield _this4.persistSeries(remoteSeries, studyUid, storeUid); return remoteSeries; })(); } streamSeriesInstances(seriesUid, storeUid) { return this.rxdbManager.dicomInstances$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(col => col.find({ selector: { seriesUid, storeUid } }).$)); } streamSeriesCacheProgress(seriesUid, storeUid) { // Scoped prefetches can complete before the rest of a multiphase series. // Derive progress from persisted attachments so the denominator is stable. return this.streamSeriesInstances(seriesUid, storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(documents => this.getSeriesProgressFromDocuments(documents))); } streamSeriesCacheProgressBySeries(seriesUids, storeUid) { return this.rxdbManager.dicomInstances$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(col => col.find({ selector: { seriesUid: { $in: seriesUids }, storeUid } }).$), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(documents => this.groupProgressBySeries(documents, seriesUids))); } groupProgressBySeries(documents, seriesUids) { const bySeries = new Map(); for (const document_ of documents) { const bucket = bySeries.get(document_.seriesUid); if (bucket) bucket.push(document_);else bySeries.set(document_.seriesUid, [document_]); } return Object.fromEntries(seriesUids.map(seriesUid => [seriesUid, this.getSeriesProgressFromDocuments(bySeries.get(seriesUid) ?? [])])); } clearSeriesForStudy(studyUid, storeUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const seriesCollection = yield _this5.rxdbManager.getSeriesCollection(); const instancesCollection = yield _this5.rxdbManager.getInstancesCollection(); const documents = yield seriesCollection.find({ selector: { storeUid, studyInstanceUID: studyUid } }).exec(); const otSeriesUids = documents.filter(s => String(s.modality ?? '').trim().toUpperCase() === 'OT').map(s => s.seriesInstanceUID).filter(Boolean); if (otSeriesUids.length > 0) { const otInstances = yield instancesCollection.find({ selector: { seriesUid: { $in: otSeriesUids }, storeUid } }).exec(); for (const document_ of otInstances) { yield _this5.removeDocumentWithRetry(document_); } } for (const document_ of documents) { yield _this5.removeDocumentWithRetry(document_); } })(); } deleteLocalSeries(seriesUid, storeUid) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instancesCollection = yield _this6.rxdbManager.getInstancesCollection(); const seriesCollection = yield _this6.rxdbManager.getSeriesCollection(); const localInstances = yield instancesCollection.find({ selector: { seriesUid, storeUid, syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.LOCAL } }).exec(); if (localInstances.length > 0) { for (const document_ of localInstances) { yield _this6.removeDocumentWithRetry(document_); } } const remaining = yield instancesCollection.find({ selector: { seriesUid, storeUid } }).exec(); if (remaining.length === 0) { const seriesDocuments = yield seriesCollection.find({ selector: { seriesInstanceUID: seriesUid, storeUid } }).exec(); for (const document_ of seriesDocuments) { yield _this6.removeDocumentWithRetry(document_); } } })(); } hasLocalDicomImports() { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instancesCollection = yield _this7.rxdbManager.getInstancesCollection(); const found = yield instancesCollection.findOne({ selector: { syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.LOCAL } }).exec(); return found !== null; })(); } clearLocalImports(excludeSeriesUid) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instancesCollection = yield _this8.rxdbManager.getInstancesCollection(); const seriesCollection = yield _this8.rxdbManager.getSeriesCollection(); const instanceSelector = excludeSeriesUid ? { seriesUid: { $ne: excludeSeriesUid }, syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.LOCAL } : { syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.LOCAL }; const localInstances = yield instancesCollection.find({ selector: instanceSelector }).exec(); if (localInstances.length === 0) return; const affectedSeries = new Map(localInstances.map(document_ => [`${document_.storeUid}|${document_.seriesUid}`, { seriesUid: document_.seriesUid, storeUid: document_.storeUid }])); for (const document_ of localInstances) { yield _this8.removeDocumentWithRetry(document_); } for (const { seriesUid, storeUid } of affectedSeries.values()) { if (excludeSeriesUid && seriesUid === excludeSeriesUid) continue; const remaining = yield instancesCollection.find({ selector: { seriesUid, storeUid } }).exec(); if (remaining.length > 0) continue; const seriesDocuments = yield seriesCollection.find({ selector: { seriesInstanceUID: seriesUid, storeUid } }).exec(); for (const document_ of seriesDocuments) { yield _this8.removeDocumentWithRetry(document_); } } })(); } getStudyUidsWithOtSeries() { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this9.rxdbManager.getSeriesCollection(); const otSeries = yield collection.find({ selector: { modality: 'OT' } }).exec(); return new Set(otSeries.map(s => s.studyInstanceUID).filter(Boolean)); })(); } /** * Returns the review status for each given study, merged from its OT series * with approved > rejected > unapproved precedence. */ getStudyOtReviewStatuses(studyUids, storeUid) { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // One request budget across every study and series in the batch - see PEEK_CONCURRENCY. const limit = (0,p_limit__WEBPACK_IMPORTED_MODULE_13__["default"])(PEEK_CONCURRENCY); const result = new Map(); yield Promise.all(studyUids.map(/*#__PURE__*/function () { var _ref2 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (studyUid) { result.set(studyUid, yield _this0.resolveStudyReviewStatus(studyUid, storeUid, limit)); }); return function (_x3) { return _ref2.apply(this, arguments); }; }())); return result; })(); } /** * The store's series list is the authority on which OT series a study holds; * the local series cache only covers studies whose details were opened before, * so it only answers when the store is unreachable. */ listOtSeriesUids(studyUid, storeUid, limit) { var _this1 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const remoteSeries = yield limit(() => _this1.api.getSeriesForStudy(studyUid, storeUid)); return remoteSeries.filter(series => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.normalizeModality)(series.modality) === 'OT').map(series => series.seriesInstanceUID).filter(Boolean); } catch { const collection = yield _this1.rxdbManager.getSeriesCollection(); const localSeries = yield collection.find({ selector: { modality: 'OT', storeUid, studyInstanceUID: studyUid } }).exec(); return localSeries.map(series => series.seriesInstanceUID).filter(Boolean); } })(); } resolveStudyReviewStatus(studyUid, storeUid, limit) { var _this10 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const seriesUids = yield _this10.listOtSeriesUids(studyUid, storeUid, limit); if (seriesUids.length === 0) return 'none'; const instancesCollection = yield _this10.rxdbManager.getInstancesCollection(); const seriesStatuses = yield Promise.all(seriesUids.map(/*#__PURE__*/function () { var _ref3 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (seriesUid) { const localInstances = yield instancesCollection.find({ selector: { seriesUid, storeUid } }).exec(); return _this10.resolveSeriesReviewStatusFromStore(studyUid, seriesUid, storeUid, localInstances, limit); }); return function (_x4) { return _ref3.apply(this, arguments); }; }())); let status = 'none'; for (const seriesStatus of seriesStatuses) { status = mergeReviewStatus(status, seriesStatus); } return status; })(); } /** * The store is the source of truth: the local cache can hold a partial or * since-deleted subset of a series, so it only answers when the store is * unreachable. */ resolveSeriesReviewStatusFromStore(studyUid, seriesUid, storeUid, localInstances, limit) { var _this11 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const instances = yield limit(() => _this11.api.getInstancesForSeries(studyUid, seriesUid, storeUid)); return resolveReviewStatusFromMetas(instances.map(inst => inst.rawMetadata)); } catch { return resolveSeriesReviewStatus(localInstances); } })(); } getStudyUidForSeries(seriesUid) { var _this12 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this12.rxdbManager.getInstancesCollection(); const [first] = yield collection.find({ limit: 1, selector: { seriesUid } }).exec(); return first?.studyUid; })(); } getSeriesCacheProgress(seriesUid, storeUid) { var _this13 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this13.rxdbManager.getInstancesCollection(); const documents = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); return _this13.getSeriesProgressFromDocuments(documents); })(); } ensureSeriesCached(studyUid, seriesUid, storeUid) { var _this14 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this14.rxdbManager.getInstancesCollection(); const localInstances = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); if (localInstances.length === 0) { const remoteInstances = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this14.api.getInstancesForSeries(studyUid, seriesUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); yield _this14.saveInstances(remoteInstances, studyUid, seriesUid, storeUid); } yield _this14.prefetchSeriesBinaries(studyUid, seriesUid, storeUid); })(); } /** * Force a fresh binary download for every instance in the series, discarding * whatever is currently cached. Use before export so the pipeline always reads * the authoritative file from the DICOM store rather than a potentially stale * attachment left over from a previous session. */ refreshSeriesBinaries(studyUid, seriesUid, storeUid) { var _this15 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const prefetchKey = `${storeUid}:${seriesUid}`; // If a prefetch for this series is already running, let it settle first so we don't // remove attachments while that run is still deciding what to fetch. const inFlightPrefetch = _this15.inFlightPrefetches.get(prefetchKey); if (inFlightPrefetch) { yield inFlightPrefetch.catch(() => { // best effort; refresh continues with a fresh generation below }); } const collection = yield _this15.rxdbManager.getInstancesCollection(); const documents = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); // Remove stale attachments so prefetchSeriesBinaries re-downloads all of them. yield Promise.all(documents.map(/*#__PURE__*/function () { var _ref4 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (document_) { _this15.permanentlyFailedInstances.delete(_this15.instanceKey(document_.sopInstanceUID, storeUid)); const attachment = document_.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (attachment) yield attachment.remove(); }); return function (_x5) { return _ref4.apply(this, arguments); }; }())); yield _this15.prefetchSeriesBinaries(studyUid, seriesUid, storeUid); })(); } deleteSeriesCache(seriesUid, storeUid, candidateDocuments) { var _this16 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const normalizedSeriesUid = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.normalizeSeriesUid)(seriesUid); if (!normalizedSeriesUid) return; const collection = yield _this16.rxdbManager.getInstancesCollection(); // Reuse documents the caller already loaded (markSeriesViewed's full-store scan) when // available, so an eviction pass over several series doesn't re-run that scan per series. let documents; if (candidateDocuments) { documents = candidateDocuments.filter(document => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.normalizeSeriesUid)(document.seriesUid) === normalizedSeriesUid); } else { // Can't match "equal after trimming" via an index lookup - a stored seriesUid can carry an // arbitrary amount of whitespace (DICOM's UI value representation is historically // space-padded), so there's no fixed set of candidate strings to search for ahead of time. // Reading every cached instance for the store and filtering in memory is the only way to // catch every padded variant, same as the resync/eviction paths already do. const documentsForStore = yield collection.find({ selector: { storeUid } }).exec(); documents = documentsForStore.filter(document => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.normalizeSeriesUid)(document.seriesUid) === normalizedSeriesUid); } _this16.clearClientSideCaches(documents, seriesUid, storeUid); for (const document of documents) { if (!document) continue; yield _this16.removeDocumentWithRetry(document); } const remaining = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); console.log(`✅ Deletion complete. Remaining documents: ${remaining.length}`); if (remaining.length > 0) { console.warn('⚠️ Some documents were not deleted:', remaining.map(d => d.sopInstanceUID)); } })(); } clearClientSideCaches(documents, seriesUid, storeUid) { // Clear DICOM Image Loader cache for each instance for (const document_ of documents) { const { sopInstanceUID } = document_; try { // Must match registration format from volume-loader.service.ts const imageId = `tomoverse-dcm:${storeUid}|${seriesUid}|${sopInstanceUID}`; try { _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_12__["default"].removeImageLoadObject(imageId); console.log(`✅ Removed from cache: ${imageId}`); } catch { console.debug(`Image not in cache: ${imageId}`); } const instanceKey = this.instanceKey(sopInstanceUID, storeUid); this.inFlightFetches.delete(instanceKey); this.permanentlyFailedInstances.delete(instanceKey); } catch (error) { console.warn('Failed to clear instance cache:', error); } } this.prefetchProgressBySeriesUid.delete(seriesUid); this.inFlightPrefetches.delete(`${storeUid}:${seriesUid}`); const volumes = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_12__["default"].getVolumes(); for (const volume of volumes) { if (volume.volumeId.includes(seriesUid)) { try { _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_12__["default"].removeVolumeLoadObject(volume.volumeId); } catch (error) { console.warn('Failed to remove volume from cache:', error); } } } for (const document_ of documents) { const cacheKey = `${document_.storeUid}:${document_.seriesUid}`; this.peekedSeriesInstanceCountCache.delete(cacheKey); } } /** * Call once a series' volume has actually loaded - not speculatively before a load succeeds. * Keeps total cached instance-attachment size under MAX_CACHED_INSTANCE_BYTES, evicting the * least-recently-touched other series first. The series just viewed is never evicted here, * even if it alone exceeds the budget. */ markSeriesViewed(seriesUid, storeUid) { var _this17 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this17.rxdbManager.getInstancesCollection(); const documents = yield collection.find().exec(); const bySeries = new Map(); for (const document_ of documents) { const attachment = document_.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (!attachment) continue; const json = document_.toJSON(true); const key = `${json.storeUid}|${json.seriesUid}`; const entry = bySeries.get(key) ?? { bytes: 0, lastTouched: 0, seriesUid: json.seriesUid, storeUid: json.storeUid }; entry.bytes += attachment.length; entry.lastTouched = Math.max(entry.lastTouched, json._meta.lwt); bySeries.set(key, entry); } let totalBytes = 0; for (const entry of bySeries.values()) totalBytes += entry.bytes; const evictionCandidates = [...bySeries.values()].filter(entry => !(entry.seriesUid === seriesUid && entry.storeUid === storeUid)).toSorted((a, b) => a.lastTouched - b.lastTouched); for (const candidate of evictionCandidates) { if (totalBytes <= DicomDatabaseService.MAX_CACHED_INSTANCE_BYTES) break; yield _this17.deleteSeriesCache(candidate.seriesUid, candidate.storeUid, documents); totalBytes -= candidate.bytes; } })(); } getSeriesInstancesMetadata(studyUid, seriesUid, storeUid) { var _this18 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this18.rxdbManager.getInstancesCollection(); const localDocuments = yield collection.find({ selector: { seriesUid, storeUid }, sort: [{ instanceNumber: 'asc' }] }).exec(); if (localDocuments.length > 0) return localDocuments; return _this18.refreshSeriesInstancesMetadata(studyUid, seriesUid, storeUid); })(); } /** * Re-fetches a series' instance metadata from the store and upserts it locally, * picking up instances added since the docs were first cached (e.g. a review * recorded by another account). Cached attachments survive the upsert. */ refreshSeriesInstancesMetadata(studyUid, seriesUid, storeUid) { var _this19 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const remoteInstances = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(asRetriable(() => _this19.api.getInstancesForSeries(studyUid, seriesUid, storeUid)), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES, shouldRetry: ({ error }) => !('status' in error && (error.status === 404 || error.status === 400)) }); return _this19.saveInstances(remoteInstances, studyUid, seriesUid, storeUid); })(); } streamSeriesMetadata(studyUid, seriesUid, storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_wrapAsyncGenerator_js__WEBPACK_IMPORTED_MODULE_2__["default"])(function* () { const localDicomDocuments = yield (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_awaitAsyncGenerator_js__WEBPACK_IMPORTED_MODULE_1__["default"])(_this.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid)); for (const document of localDicomDocuments) { yield document; } })(); } getSeriesCommonMetadata(studyUid, seriesUid, storeUid) { var _this20 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const [firstInstanceMetadata] = yield _this20.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid); if (!firstInstanceMetadata) return; return _this20.mapDocumentToInstance(firstInstanceMetadata); })(); } /** * Local-only variant of getSeriesCommonMetadata: never fetches remotely at all. That fetch * exists on the caching variant so an intentional open/download re-populates metadata on a * cold cache, but for incidental display purposes (e.g. a study-summary header reacting to * whichever series is currently first in the list) it's an extra request landing on the exact * series - and exact moment - a real open is most likely to also be writing to, adding * concurrent pressure on RxDB's local storage right when it's most contended. See * peekSeriesCommonMetadata for a variant that can still reach the network on a cold cache * without those side effects, when the caller actually needs the richer fields. */ getLocalSeriesCommonMetadata(seriesUid, storeUid) { var _this21 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this21.rxdbManager.getInstancesCollection(); const [localFirstInstance] = yield collection.find({ selector: { seriesUid, storeUid }, sort: [{ instanceNumber: 'asc' }] }).exec(); if (!localFirstInstance) return; return _this21.mapDocumentToInstance(localFirstInstance); })(); } /** * Same summary fields as getSeriesCommonMetadata (patient/study info for a heading, etc.), but * never persists anything locally: on a cold cache it reads the network response straight off * the wire (DicomApiService already returns each instance's raw DICOM-JSON as `rawMetadata`) * instead of routing it through saveInstances. Unlike the caching variant, this can't grow * local storage or resurrect a previously-evicted series' metadata rows just to populate a * display label. */ peekSeriesCommonMetadata(studyUid, seriesUid, storeUid) { var _this22 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const local = yield _this22.getLocalSeriesCommonMetadata(seriesUid, storeUid); if (local) return local; const remoteInstances = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(asRetriable(() => _this22.api.getInstancesForSeries(studyUid, seriesUid, storeUid)), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES, shouldRetry: ({ error }) => !('status' in error && (error.status === 404 || error.status === 400)) }); const [first] = remoteInstances; if (!first?.sopInstanceUID) return; return _this22.mapDocumentToInstance({ metadata: first.rawMetadata, seriesUid, sopInstanceUID: first.sopInstanceUID, studyUid }); })(); } /** * True instance total across every series in the study, without persisting anything locally. * Some stores' study-search response already carries a study-level count (see * StudySearchRow.numberOfInstances), which is far cheaper and should be preferred when * present - this exists for when it isn't (that field is vendor-dependent and can be absent). */ peekStudyInstanceCount(studyUid, storeUid) { var _this23 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const counts = yield _this23.peekSeriesInstanceCounts(studyUid, storeUid); return [...counts.values()].reduce((sum, count) => sum + count, 0); })(); } /** * Per-series instance totals for a study, keyed by seriesInstanceUID - the true count on the * store regardless of what's cached locally, for display purposes (e.g. a series table's * "Images" column) that shouldn't be limited to whatever happens to already be downloaded. * Same peek semantics as peekSeriesCommonMetadata (local-first, network fallback, never * persists), capped at PEEK_CONCURRENCY concurrent network requests. * * Series resolve in parallel (up to PEEK_CONCURRENCY at a time) and not necessarily in list * order - onSeriesCount, when given, fires as each one lands so a caller can render counts * incrementally instead of waiting for the slowest series to show any of them. */ peekSeriesInstanceCounts(studyUid, storeUid, onSeriesCount) { var _this24 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const series = yield _this24.peekSeriesForStudy(studyUid, storeUid); const limit = (0,p_limit__WEBPACK_IMPORTED_MODULE_13__["default"])(PEEK_CONCURRENCY); const entries = yield Promise.all(series.map(/*#__PURE__*/function () { var _ref5 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({ seriesInstanceUID }) { if (!seriesInstanceUID) return; const count = yield limit(() => _this24.peekSeriesInstanceCount(studyUid, seriesInstanceUID, storeUid)); onSeriesCount?.(seriesInstanceUID, count); return [seriesInstanceUID, count]; }); return function (_x6) { return _ref5.apply(this, arguments); }; }())); return new Map(entries.filter(entry => entry !== undefined)); })(); } /** * Same series list as getSeriesForStudy, but on a cache miss calls the API client directly * instead of getSeriesForStudy itself - that method persists a cold-cache fetch via * persistSeries, which would defeat peekStudyInstanceCount's whole point of never writing to * local storage just to compute a display count. */ peekSeriesForStudy(studyUid, storeUid) { var _this25 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this25.rxdbManager.getSeriesCollection(); const localSeries = yield collection.find({ selector: { storeUid, studyInstanceUID: studyUid }, sort: [{ seriesNumber: 'asc' }] }).exec(); if (localSeries.length > 0) return localSeries.map(series => series.toJSON()); return (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this25.api.getSeriesForStudy(studyUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); })(); } peekSeriesInstanceCount(studyUid, seriesUid, storeUid) { var _this26 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const cacheKey = `${storeUid}:${seriesUid}`; const cached = _this26.peekedSeriesInstanceCountCache.get(cacheKey); if (cached !== undefined) return cached; const generation = _this26.peekedSeriesInstanceCountCacheGeneration; const collection = yield _this26.rxdbManager.getInstancesCollection(); const localDocuments = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); if (localDocuments.length > 0) { if (generation === _this26.peekedSeriesInstanceCountCacheGeneration) { _this26.peekedSeriesInstanceCountCache.set(cacheKey, localDocuments.length); } return localDocuments.length; } const remoteInstances = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(asRetriable(() => _this26.api.getInstancesForSeries(studyUid, seriesUid, storeUid)), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES, shouldRetry: ({ error }) => !('status' in error && (error.status === 404 || error.status === 400)) }); // Sign-out (clearPeekCache) may have happened while the read/network call above was in // flight - don't let a stale peek from the previous session repopulate the cache it just // cleared. The caller still gets the correct, freshly-fetched count either way. if (generation === _this26.peekedSeriesInstanceCountCacheGeneration) { _this26.peekedSeriesInstanceCountCache.set(cacheKey, remoteInstances.length); } return remoteInstances.length; })(); } /** Clears the session-scoped peek cache above - called on logout so the next account signing * in on the same tab doesn't see a previous account's peeked counts. */ clearPeekCache() { this.peekedSeriesInstanceCountCache.clear(); this.peekedSeriesInstanceCountCacheGeneration++; } getInstance(sopUID, storeUid) { var _this27 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this27.rxdbManager.getInstancesCollection(); return yield collection.findOne((0,_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_15__.dicomInstanceId)(storeUid, sopUID)).exec(); })(); } saveInstances(instances, studyUid, seriesUid, storeUid) { var _this28 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this28.rxdbManager.getInstancesCollection(); const { success: savedInstances } = yield collection.bulkUpsert(instances.filter(instance => Boolean(instance.sopInstanceUID)).map(({ instanceNumber, rawMetadata: metadata, sopInstanceUID }) => ({ createdAt: Date.now(), id: (0,_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_15__.dicomInstanceId)(storeUid, sopInstanceUID), instanceNumber, metadata, seriesUid, sopInstanceUID, storeUid, studyUid, syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.SYNCED }))); return savedInstances.toSorted((a, b) => a.instanceNumber - b.instanceNumber); })(); } getSeriesInstanceFiles(seriesUid, storeUid) { var _this29 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this29.rxdbManager.getInstancesCollection(); const documents = yield collection.find({ selector: { seriesUid, storeUid } }).exec(); const files = []; for (const document_ of documents) { const attachment = document_.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (attachment) { files.push(yield attachment.getData().then(data => _this29.attachmentDataToArrayBuffer(data))); } } return files; })(); } /** Returns an instance's pixel data only if already cached locally - never fetches over the network. */ getCachedBinary(sopInstanceUID, storeUid) { var _this30 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const dicomDocument = yield _this30.getInstance(sopInstanceUID, storeUid); const attachment = dicomDocument?.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (!attachment) return undefined; try { return yield attachment.getData().then(data => _this30.attachmentDataToArrayBuffer(data)); } catch (error) { // See loadBinaryUncached - a concurrent deleteSeriesCache can remove this attachment's // underlying data between the stale reference above and this read. Not cached is // exactly the right answer at that point, not a thrown error. if (_this30.isConcurrentDeletionError(error)) return undefined; throw error; } })(); } getBinary(sopInstanceUID, storeUid) { var _this31 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const key = _this31.instanceKey(sopInstanceUID, storeUid); // Registered synchronously, before any await, so two calls made back-to-back can never // both slip past this check - whichever call happens first always wins the race, even if // the two calls' subsequent async work (e.g. an RxDB lookup) later resolves in either order. const existingFetch = _this31.inFlightFetches.get(key); if (existingFetch) return existingFetch; const fetchPromise = _this31.loadBinaryUncached(sopInstanceUID, storeUid, key); _this31.inFlightFetches.set(key, fetchPromise); return fetchPromise.finally(() => _this31.inFlightFetches.delete(key)); })(); } /** * `getAttachment` reads the attachment's metadata off the (possibly already stale) in-memory * document reference synchronously - it can report an attachment present a moment after a * concurrent deleteSeriesCache has removed that attachment's underlying data. The actual * read only happens on `getData()`, which is where that race surfaces as a raw * NotFoundError instead of the "not cached" case this is functionally equivalent to. */ isConcurrentDeletionError(error) { return error instanceof Error && error.name === 'NotFoundError'; } isQuotaExceededError(error) { return error instanceof DOMException && error.name === 'QuotaExceededError' || error instanceof Error && error.name === 'QuotaExceededError'; } loadBinaryUncached(sopInstanceUID, storeUid, key) { var _this32 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const dicomDocument = yield _this32.getInstance(sopInstanceUID, storeUid); if (!dicomDocument) throw new Error(`Dicom document ${sopInstanceUID} not found.`); const attachment = dicomDocument.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (attachment) { try { return yield attachment.getData().then(data => _this32.attachmentDataToArrayBuffer(data)); } catch (error) { // Fall through to the network path exactly as if there'd been no attachment at all. If // the document is genuinely gone, saveBinary's own already-deleted check (TVC-1182) // makes the resulting cache-write a safe no-op instead of resurrecting it. if (!_this32.isConcurrentDeletionError(error)) throw error; } } return _this32.fetchOverNetworkAndCache(sopInstanceUID, storeUid, dicomDocument.studyUid, dicomDocument.seriesUid, key); })(); } // Split out of getBinary so callers that already have studyUid/seriesUid in hand (like // prefetchInstanceBinaries, iterating documents it already fetched) skip a redundant per- // instance RxDB lookup - that lookup, multiplied over a large series, was adding real latency // to store/series navigation once prefetch started routing through this for deduping. fetchAndCacheBinary(sopInstanceUID, storeUid, studyUid, seriesUid) { const key = this.instanceKey(sopInstanceUID, storeUid); const existingFetch = this.inFlightFetches.get(key); if (existingFetch) return existingFetch; const fetchPromise = this.fetchOverNetworkAndCache(sopInstanceUID, storeUid, studyUid, seriesUid, key); this.inFlightFetches.set(key, fetchPromise); return fetchPromise.finally(() => this.inFlightFetches.delete(key)); } isSaveBinaryTimeoutError(error) { return error instanceof Error && error.message.includes(SAVE_BINARY_TIMEOUT_PREFIX); } // Never calls back into getBinary/fetchAndCacheBinary's own in-flight registration - both of // those already register themselves under `key` before calling this, so doing it again here // would just await their own already-registered promise (a deadlock). fetchOverNetworkAndCache(sopInstanceUID, storeUid, studyUid, seriesUid, key) { var _this33 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this33.permanentlyFailedInstances.has(key)) { throw new Error(`Dicom instance ${sopInstanceUID} previously failed permanently, not retrying`); } try { const buffer = yield _this33.networkFetchLimit(() => (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(asRetriable(() => _this33.api.getInstanceDicomFile(studyUid, seriesUid, sopInstanceUID, storeUid)), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES, shouldRetry: ({ error }) => !('status' in error && (error.status === 404 || error.status === 400)) })); yield _this33.cacheBinary(sopInstanceUID, buffer, storeUid, seriesUid); return buffer; } catch (error) { if (error && typeof error === 'object' && 'status' in error) { const status = error.status; if (status === 400 || status === 404) { _this33.permanentlyFailedInstances.add(key); } } throw error; } })(); } /** * Persists a freshly fetched binary, retrying transient write failures via pRetry. On an * IndexedDB QuotaExceededError (the retry can't help without freeing space) it instead evicts * the least-recently-touched other series once and retries the write; if there is nothing to * evict, eviction fails, or the retry still fails, it gives up on caching rather than failing * the whole fetch - the buffer was already downloaded, so image loading still succeeds. */ cacheBinary(sopInstanceUID, buffer, storeUid, seriesUid) { var _this34 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const writePromise = _this34.saveBinary(sopInstanceUID, buffer, storeUid); try { yield (0,_tomoverse_utils_promises__WEBPACK_IMPORTED_MODULE_20__.withTimeout)(writePromise, SAVE_BINARY_TIMEOUT_MS, `${SAVE_BINARY_TIMEOUT_PREFIX} ${sopInstanceUID} - the local write got stuck.`); } catch (error) { if (_this34.isSaveBinaryTimeoutError(error)) { // Prevent overlapping retries while the original write may still be in flight. yield writePromise.catch(() => { // swallow: original error is rethrown below }); } throw error; } }), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES, shouldRetry: ({ error }) => !_this34.isSaveBinaryTimeoutError(error) && !_this34.isQuotaExceededError(error) }); } catch (error) { if (!_this34.isQuotaExceededError(error)) throw error; try { const evicted = yield _this34.evictLeastRecentlyTouchedSeries(seriesUid, storeUid); if (!evicted) return; yield _this34.saveBinary(sopInstanceUID, buffer, storeUid); } catch { // Best-effort: reclamation or the retry failed, so leave the buffer uncached. } } })(); } /** * Evicts the least-recently-touched cached series other than the one identified by * (excludeSeriesUid, excludeStoreUid) - that series is never evicted by its own write path. * Returns false when there is no other cached series to reclaim. Reuses the same persisted * last-write-time ordering as markSeriesViewed so cross-session "least recently used" holds. */ evictLeastRecentlyTouchedSeries(excludeSeriesUid, excludeStoreUid) { var _this35 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this35.rxdbManager.getInstancesCollection(); const documents = yield collection.find().exec(); const bySeries = new Map(); for (const document_ of documents) { const attachment = document_.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (!attachment) continue; const json = document_.toJSON(true); const key = `${json.storeUid}|${json.seriesUid}`; const entry = bySeries.get(key); if (!entry || json._meta.lwt > entry.lastTouched) { bySeries.set(key, { lastTouched: json._meta.lwt, seriesUid: json.seriesUid, storeUid: json.storeUid }); } } const candidate = [...bySeries.values()].filter(entry => !(entry.seriesUid === excludeSeriesUid && entry.storeUid === excludeStoreUid)).toSorted((a, b) => a.lastTouched - b.lastTouched)[0]; if (!candidate) return false; yield _this35.deleteSeriesCache(candidate.seriesUid, candidate.storeUid); return true; })(); } prefetchSeriesBinaries(studyUid, seriesUid, storeUid) { var _this36 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this36.prefetchInstanceBinaries(studyUid, seriesUid, storeUid); })(); } // Omit sopInstanceUIDs for the whole series. prefetchInstanceBinaries(studyUid, seriesUid, storeUid, sopInstanceUIDs) { var _this37 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const key = `${storeUid}:${seriesUid}`; const existing = _this37.inFlightPrefetches.get(key); if (existing) return existing; const prefetchPromise = _this37.prefetchInstanceBinariesUncached(studyUid, seriesUid, storeUid, sopInstanceUIDs); _this37.inFlightPrefetches.set(key, prefetchPromise); return prefetchPromise.finally(() => _this37.inFlightPrefetches.delete(key)); })(); } prefetchInstanceBinariesUncached(studyUid, seriesUid, storeUid, sopInstanceUIDs) { var _this38 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const progressSubject = _this38.getPrefetchProgressSubject(seriesUid); try { const documents = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this38.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); const wanted = sopInstanceUIDs ? new Set(sopInstanceUIDs) : undefined; const scopedDocuments = documents.filter(document => !wanted || wanted.has(document.sopInstanceUID)); const totalCount = scopedDocuments.length; let cachedCount = scopedDocuments.filter(document => document.getAttachment(PIXEL_DATA_ATTACHMENT_NAME)).length; _this38.emitPrefetchProgress(progressSubject, { cachedCount, percent: _this38.progressPercent(cachedCount, totalCount), totalCount }); // No pLimit wrapper here - fetchAndCacheBinary's actual network call already queues on the // shared networkFetchLimit, which is what needs to stay a single global bound (see its // comment). A second, separately-sized limiter here would just be redundant bookkeeping. yield Promise.all(scopedDocuments.filter(document => !document.getAttachment(PIXEL_DATA_ATTACHMENT_NAME)).map(/*#__PURE__*/function () { var _ref7 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({ sopInstanceUID }) { const key = _this38.instanceKey(sopInstanceUID, storeUid); if (_this38.permanentlyFailedInstances.has(key)) return; try { // Shares fetchAndCacheBinary with getBinary rather than fetching independently - // Cornerstone's own on-demand per-image loading calls getBinary too, and on a // cold cache both this background prefetch and that on-demand load race to fetch // the same instance; the shared in-flight dedup collapses that into one request // instead of two concurrent ones hitting the store. studyUid/seriesUid are // already known here, so this skips getBinary's per-instance document lookup. yield _this38.fetchAndCacheBinary(sopInstanceUID, storeUid, studyUid, seriesUid); cachedCount += 1; _this38.emitPrefetchProgress(progressSubject, { cachedCount, percent: _this38.progressPercent(cachedCount, totalCount), totalCount }); } catch (error) { if (_this38.permanentlyFailedInstances.has(key)) return; throw error; } }); return function (_x7) { return _ref7.apply(this, arguments); }; }())); } finally { _this38.removePrefetchProgressSubject(seriesUid, progressSubject); } })(); } getSeriesImageUrls(studyUid, seriesUid, storeUid) { var _this39 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instances = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this39.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); const limit = (0,p_limit__WEBPACK_IMPORTED_MODULE_13__["default"])(FETCH_CONCURRENCY); return yield Promise.all(instances.map(instance => limit(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const blob = yield (0,p_retry__WEBPACK_IMPORTED_MODULE_14__["default"])(() => _this39.api.getInstanceImage(studyUid, seriesUid, instance.sopInstanceUID, storeUid), { minTimeout: FETCH_MIN_RETRY_TIMEOUT, retries: FETCH_RETRIES }); const objectUrl = URL.createObjectURL(blob); // eslint-disable-next-line sonarjs/no-angular-bypass-sanitization return _this39.sanitizer.bypassSecurityTrustUrl(objectUrl); })))); })(); } /** * A concurrent removeDocumentWithRetry (e.g. the user deleting this series' local cache while * this binary is still being fetched in the background) can delete the document between * getInstance's lookup and putAttachment's write, or between that write being queued and RxDB's * incrementalWriteQueue actually running it against the latest (now-deleted) revision - either * way putAttachment throws (surfaced to the user as "Document update conflict" - TVC-1182). * Deliberately not a retry-and-write-anyway like removeDocumentWithRetry's: the user's delete * is the one action here with explicit intent, so a cache write losing that race should be * abandoned instead of resurrecting data onto a document the user just removed. */ saveBinary(sopUID, buffer, storeUid) { var _this40 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const dicomDocument = yield _this40.getInstance(sopUID, storeUid); if (!dicomDocument || dicomDocument.deleted) return; try { yield dicomDocument.putAttachment({ data: (0,_rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_21__.toRxdbAttachmentBinary)(buffer), id: PIXEL_DATA_ATTACHMENT_NAME, type: 'application/dicom' }); } catch (error) { // getLatest() is a synchronous read from RxDB's in-memory doc cache, not a query - it // reflects the delete even if it landed after our stale dicomDocument reference was read. if (dicomDocument.getLatest().deleted) return; throw error; } })(); } attachmentDataToArrayBuffer(data) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (typeof data === 'object' && data !== null && 'arrayBuffer' in data && typeof data.arrayBuffer === 'function') { return yield data.arrayBuffer(); } if (data instanceof ArrayBuffer) { return data; } if (ArrayBuffer.isView(data)) { const copy = new Uint8Array(data.byteLength); copy.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); return copy.buffer; } throw new TypeError('Unsupported attachment data type'); })(); } deleteBinary(sopUID, storeUid) { var _this41 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const dicomDocument = yield _this41.getInstance(sopUID, storeUid); const attachment = dicomDocument?.getAttachment(PIXEL_DATA_ATTACHMENT_NAME); if (attachment) yield attachment.remove(); })(); } getAllNotUploadedSeries(storeUid) { const seriesResults$ = this.rxdbManager.dicomSeries$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.filter)(collection => !collection.closed), (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(collection => collection.find({ selector: { storeUid } }).$), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.catchError)(() => rxjs__WEBPACK_IMPORTED_MODULE_7__.EMPTY)); const instanceResults$ = this.rxdbManager.dicomInstances$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.filter)(collection => !collection.closed), (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(collection => collection.find({ selector: { storeUid } }).$), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.catchError)(() => rxjs__WEBPACK_IMPORTED_MODULE_7__.EMPTY)); return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.combineLatest)([seriesResults$, instanceResults$]).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(([seriesDocuments, instanceDocuments]) => { const statusesBySeriesUid = new Map(); for (const instanceDocument of instanceDocuments) { const statuses = statusesBySeriesUid.get(instanceDocument.seriesUid); if (statuses) { statuses.push({ syncStatus: instanceDocument.syncStatus }); } else { statusesBySeriesUid.set(instanceDocument.seriesUid, [{ syncStatus: instanceDocument.syncStatus }]); } } return seriesDocuments.map(seriesDocument => ({ ...seriesDocument.toJSON(), instances: statusesBySeriesUid.get(seriesDocument.seriesInstanceUID ?? '') ?? [] })).filter(series => series.instances.some(instance => instance.syncStatus !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.RxDBSyncStatus.SYNCED)); })); } getSeriesProgressFromDocuments(documents) { if (documents.length === 0) return { cachedCount: 0, percent: 0, totalCount: 0 }; const cachedCount = documents.filter(({ getAttachment }) => !!getAttachment(PIXEL_DATA_ATTACHMENT_NAME)).length; const totalCount = documents.length; return { cachedCount, percent: this.progressPercent(cachedCount, totalCount), totalCount }; } progressPercent(cachedCount, totalCount) { if (totalCount === 0) return 0; return Math.round(cachedCount / totalCount * 100); } prefetchProgressStream(seriesUid) { return this.getPrefetchProgressSubject(seriesUid).asObservable(); } emitPrefetchProgress(subject, progress) { console.debug(`[viewer-debug] prefetch progress: ${progress.cachedCount}/${progress.totalCount} (${progress.percent}%)`); subject.next(progress); } getPrefetchProgressSubject(seriesUid) { const existing = this.prefetchProgressBySeriesUid.get(seriesUid); if (existing) return existing; const subject = new rxjs__WEBPACK_IMPORTED_MODULE_5__.ReplaySubject(1); this.prefetchProgressBySeriesUid.set(seriesUid, subject); return subject; } removePrefetchProgressSubject(seriesUid, subject) { if (this.prefetchProgressBySeriesUid.get(seriesUid) === subject) { this.prefetchProgressBySeriesUid.delete(seriesUid); } } persistSeries(_x8, _x9, _x0) { var _this42 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (seriesList, studyUid, storeUid, shouldPersist = () => true) { const collection = yield _this42.rxdbManager.getSeriesCollection(); // Re-checked here, right before the write: the caller's condition (e.g. "is this // still the active request") may have flipped during the getSeriesCollection() await, // and a stale write here could re-add series a concurrent resync just deleted. if (!shouldPersist()) return; const payload = seriesList.filter(series => Boolean(series.seriesInstanceUID)).map(series => ({ ...series, createdAt: Date.now(), id: (0,_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_15__.dicomSeriesId)(storeUid, series.seriesInstanceUID), storeUid, studyInstanceUID: studyUid })); if (payload.length === 0) return; const { error } = yield collection.bulkUpsert(payload); if (error.length === 0) return; // bulkUpsert's error array isn't conflicts-only (status can be 409 conflict, 422 validation, // or 510 attachment) - only 409s are safe to self-heal here, so anything else is surfaced // instead of being retried against the same payload that just failed. const nonConflictErrors = error.filter(({ status }) => status !== 409); if (nonConflictErrors.length > 0) { throw new Error(`Failed to persist ${nonConflictErrors.length} of ${payload.length} series documents ` + `(status ${nonConflictErrors.map(({ status }) => status).join(', ')}).`); } // A concurrent write can bump a document's revision between building this payload and // committing it, silently dropping the conflicting rows. Resolve each one through // incrementalUpsert instead of a second bulk write: it re-reads the document's current state // and applies the change via RxDB's normal single-document write path, queued per document id // so it can't re-race. const conflictedIds = new Set(error.map(({ documentId }) => documentId)); const conflicted = payload.filter(document_ => conflictedIds.has(document_.id)); yield Promise.all(conflicted.map(document_ => collection.incrementalUpsert(document_))); }).apply(this, arguments); } getSeriesComputedMetadata(studyUid, seriesUid, storeUid) { var _this43 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const computedMetadata = yield _this43.computeInstanceMetadata(studyUid, seriesUid, storeUid); if (!computedMetadata) return; const { instanceCount, isCardiacGated, mappedInstanceDocuments, missingInstancesDetected, modalities: [...modalities], totalFileSizeMb } = computedMetadata; const firstPopulatedInstanceDocument = mappedInstanceDocuments[0]; if (!firstPopulatedInstanceDocument) return; const { columns, numberOfTemporalPositions, rows, sliceOrientation, sliceThickness, transferSyntaxUID } = firstPopulatedInstanceDocument; const matrixSize = rows && columns ? `${columns}×${rows}` : undefined; return { compression: transferSyntaxUID, fileSizeMb: totalFileSizeMb > 0 ? Number.parseFloat(totalFileSizeMb.toFixed(2)) : undefined, instanceCount, isCardiacGated, isVolumetric: (numberOfTemporalPositions ?? 1) > 1, mappedInstanceDocuments, matrixSize, missingInstancesDetected, modalities, numberOfTemporalPositions: numberOfTemporalPositions ?? 1, sliceOrientation, sliceThickness }; })(); } computeInstanceMetadata(studyUid, seriesUid, storeUid) { var _this44 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instances = yield _this44.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid); if (instances.length === 0) return; const mappedInstanceDocuments = []; const modalities = new Set(); const seenInstanceIds = new Set(); let totalFileSizeMb = 0; let isCardiacGated = false; for (const instance of instances) { const attachment = instance.getAttachment('pixelData'); if (attachment) totalFileSizeMb += attachment.length / (1024 * 1024); const mappedDocument = _this44.mapDocumentToInstance(instance); if (mappedDocument !== undefined) { isCardiacGated = isCardiacGated || mappedDocument.triggerTime !== undefined || mappedDocument.cardiacNumberOfImages !== undefined; const instanceId = mappedDocument.instanceNumber; if (instanceId !== undefined) { seenInstanceIds.add(instanceId); } if (mappedDocument.modality) { modalities.add(mappedDocument.modality); } mappedInstanceDocuments.push(mappedDocument); } } return { instanceCount: instances.length, isCardiacGated, mappedInstanceDocuments, missingInstancesDetected: seenInstanceIds.size < instances.length, modalities: [...modalities], totalFileSizeMb }; })(); } mapDocumentToInstance({ metadata, seriesUid, sopInstanceUID, studyUid }) { if (!metadata) return; const typedMetadata = metadata; return { accessionNumber: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.AccessionNumber), bitsAllocated: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.BitsAllocated), bitsStored: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.BitsStored), cardiacNumberOfImages: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.CardiacNumberOfImages), columns: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.Columns), highBit: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.HighBit), imageOrientationPatient: typedMetadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.ImageOrientationPatient]?.Value, imagePositionPatient: typedMetadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.ImagePositionPatient]?.Value, instanceNumber: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.InstanceNumber), institutionName: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.InstitutionName), modality: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.Modality), numberOfTemporalPositions: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.NumberOfTemporalPositions), patientBirthDate: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PatientBirthDate), patientID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PatientID), patientName: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PatientName)?.Alphabetic, patientSex: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PatientSex), photometricInterpretation: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PhotometricInterpretation), pixelRepresentation: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PixelRepresentation), pixelSpacing: typedMetadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.PixelSpacing]?.Value, rawMetadata: metadata, rescaleIntercept: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.RescaleIntercept), rescaleSlope: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.RescaleSlope), rows: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.Rows), samplesPerPixel: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SamplesPerPixel), seriesDate: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SeriesDate), seriesDescription: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SeriesDescription), seriesInstanceUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SeriesInstanceUID) ?? seriesUid, seriesNumber: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SeriesNumber), seriesTime: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SeriesTime), sliceLocation: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SliceLocation), sliceOrientation: 'Axial', // For now, it's always going to be Axial sliceThickness: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.SliceThickness), sopInstanceUID: sopInstanceUID, studyDate: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.StudyDate), studyDescription: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.StudyDescription), studyID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.StudyID), studyInstanceUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.StudyInstanceUID) ?? studyUid, studyTime: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.StudyTime), temporalPositionIdentifier: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.TemporalPositionIdentifier), transferSyntaxUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.TransferSyntaxUID), triggerTime: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.TriggerTime), windowCenter: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.WindowCenter), windowWidth: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_18__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_17__.DicomTagId.WindowWidth) }; } static ɵfac = function DicomDatabaseService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomDatabaseService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"]({ token: DicomDatabaseService, factory: DicomDatabaseService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 67189 /*!*************************************************************!*\ !*** ./libs/data-access/src/lib/db/rxdb-manager.service.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RXDB_CONFIG: () => (/* binding */ RXDB_CONFIG), /* harmony export */ RXDB_DEFAULT_STORAGE: () => (/* binding */ RXDB_DEFAULT_STORAGE), /* harmony export */ RxdbManager: () => (/* binding */ RxdbManager) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 87675); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 27588); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxdb */ 49813); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxdb */ 39352); /* harmony import */ var rxdb_premium_plugins_storage_indexeddb__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxdb-premium/plugins/storage-indexeddb */ 5775); /* harmony import */ var rxdb_plugins_attachments__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxdb/plugins/attachments */ 17850); /* harmony import */ var rxdb_plugins_cleanup__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxdb/plugins/cleanup */ 26240); /* harmony import */ var rxdb_plugins_dev_mode__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxdb/plugins/dev-mode */ 64585); /* harmony import */ var rxdb_plugins_leader_election__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxdb/plugins/leader-election */ 5019); /* harmony import */ var rxdb_plugins_local_documents__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! rxdb/plugins/local-documents */ 70712); /* harmony import */ var rxdb_plugins_migration_schema__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! rxdb/plugins/migration-schema */ 70400); /* harmony import */ var rxdb_plugins_update__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxdb/plugins/update */ 25757); /* harmony import */ var rxdb_plugins_validate_ajv__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! rxdb/plugins/validate-ajv */ 228); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); /* harmony import */ var _services_auth_service__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../services/auth.service */ 52807); /* harmony import */ var _work_session_work_session_collection__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./work-session/work-session.collection */ 32159); const RXDB_CONFIG = new _angular_core__WEBPACK_IMPORTED_MODULE_2__.InjectionToken('RXDB_CONFIG'); const RXDB_DEFAULT_STORAGE = new _angular_core__WEBPACK_IMPORTED_MODULE_2__.InjectionToken('RXDB_DEFAULT_STORAGE', { factory: () => rxdb_premium_plugins_storage_indexeddb__WEBPACK_IMPORTED_MODULE_10__.getRxStorageIndexedDB, providedIn: 'root' }); class RxdbManager { http = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient); authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_services_auth_service__WEBPACK_IMPORTED_MODULE_21__.AuthService); config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(RXDB_CONFIG); defaultStorage = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(RXDB_DEFAULT_STORAGE); currentDb; dbInstance$ = new rxjs__WEBPACK_IMPORTED_MODULE_3__.ReplaySubject(1); workSessionReplicationState; // Set once by init() - remove() needs the same resolved name used when the database was // opened, not just this.config.name (which may be undefined and fall back to // defaultRxdbConfig.name). resolvedDatabaseName; init() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this.currentDb) return; const { apiUrl, devMode, name, options, storage } = { ..._tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_20__.defaultRxdbConfig, ..._this.config }; const resolvedDatabaseName = name ?? _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_20__.defaultRxdbConfig.name; _this.resolvedDatabaseName = resolvedDatabaseName; const resolvedStorage = storage ?? _this.defaultStorage(); _this.setupPlugins(devMode); const { database, workSessionReplicationState } = yield _this.openDatabase(resolvedDatabaseName, resolvedStorage, options, apiUrl); _this.currentDb = database; _this.workSessionReplicationState = workSessionReplicationState; _this.dbInstance$.next(database); })(); } openDatabase(name, storage, options, apiUrl) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const database = yield (0,rxdb__WEBPACK_IMPORTED_MODULE_9__.createRxDatabase)({ name, storage: (0,rxdb_plugins_validate_ajv__WEBPACK_IMPORTED_MODULE_18__.wrappedValidateAjvStorage)({ storage }), ...options }); try { yield database.addCollections({ dicomInstances: { // v0 to v1 added the store-scoped composite primary key. Pre-store docs // can't be re-keyed (no storeUid), so drop them. They re-fetch on demand. // v1 to v2 only added an index on syncStatus; no data shape change. // eslint-disable-next-line unicorn/no-null migrationStrategies: { 1: () => null, 2: instanceDocument => instanceDocument }, schema: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_19__.dicomSchema }, dicomSeries: { // eslint-disable-next-line unicorn/no-null migrationStrategies: { 1: () => null, 2: seriesDocument => seriesDocument }, schema: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_19__.dicomSeriesSchema } }); const workSessionReplicationState = yield (0,_work_session_work_session_collection__WEBPACK_IMPORTED_MODULE_22__.setupWorkSessionCollection)(database, _this2.http, _this2.authService, apiUrl); return { database, workSessionReplicationState }; } catch (error) { // Release any handles this partially-opened database holds before the failure propagates, // so a leaked handle from this failed attempt can't interfere with a later retry. yield database.close().catch(() => { // Best-effort - the original error above is what actually gets propagated. }); throw error; } })(); } // Bounded: awaitInSync retries forever while offline, and callers (sign-out) // must not hang on it. awaitWorkSessionsInSync() { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (timeoutMs = 5000) { const replicationState = _this3.workSessionReplicationState; if (!replicationState) return; yield Promise.race([replicationState.awaitInSync(), new Promise(resolve => setTimeout(resolve, timeoutMs))]); }).apply(this, arguments); } // Destructive cleanup: cancels replication, closes the database, and deletes the local RxDB // cache. Use when the signed-in user's session data must be discarded. remove() { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!_this4.currentDb) { const { name, options, storage } = { ..._tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_20__.defaultRxdbConfig, ..._this4.config }; yield (0,rxdb__WEBPACK_IMPORTED_MODULE_9__.removeRxDatabase)(_this4.resolvedDatabaseName ?? name ?? _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_20__.defaultRxdbConfig.name, (0,rxdb_plugins_validate_ajv__WEBPACK_IMPORTED_MODULE_18__.wrappedValidateAjvStorage)({ storage: storage ?? _this4.defaultStorage() }), options?.multiInstance, options?.password); return; } const database = _this4.currentDb; _this4.dbInstance$.next(undefined); yield _this4.workSessionReplicationState?.cancel(); _this4.workSessionReplicationState = undefined; yield database.remove(); _this4.currentDb = undefined; })(); } get activeDb$() { return this.dbInstance$.asObservable(); } // The closed-collection filter must sit AFTER shareReplay(1), not before it: shareReplay caches // whatever value last passed through, and that collection is always still open at the moment it // flows through map() - it only becomes closed *later*, in place, via a separate remove() call // that never pushes a new value through this pipe. A filter placed before shareReplay would // never actually catch that (it only ever sees the collection while it's still open); placed // after, it re-evaluates .closed on every delivery, including replayed ones, so a new // subscriber joining between a remove() and the next init() (e.g. a cold boot's initial "not // authenticated yet" tick before sign-in completes) doesn't get handed the stale, closed // collection RxDB's live-query engine can never recover a result from - it correctly waits for // the next (valid) emission instead. Before this, only a full page reload recovered from that. dicomSeries$ = this.activeDb$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.map)(database => database.dicomSeries), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.shareReplay)(1), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(collection => !collection.closed)); dicomInstances$ = this.activeDb$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.map)(database => database.dicomInstances), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.shareReplay)(1), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(collection => !collection.closed)); workSessions$ = this.activeDb$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.map)(database => database?.workSession), (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.shareReplay)(1)); getSeriesCollection() { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return yield (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.firstValueFrom)(_this5.dicomSeries$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(collection => !collection.closed))); })(); } getInstancesCollection() { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return yield (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.firstValueFrom)(_this6.dicomInstances$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(collection => !collection.closed))); })(); } getWorkSessionCollection() { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.firstValueFrom)(_this7.workSessions$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(collection => !!collection && !collection.closed))); })(); } setupPlugins(devMode) { (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_attachments__WEBPACK_IMPORTED_MODULE_11__.RxDBAttachmentsPlugin); (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_cleanup__WEBPACK_IMPORTED_MODULE_12__.RxDBCleanupPlugin); (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_leader_election__WEBPACK_IMPORTED_MODULE_14__.RxDBLeaderElectionPlugin); (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_local_documents__WEBPACK_IMPORTED_MODULE_15__.RxDBLocalDocumentsPlugin); (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_migration_schema__WEBPACK_IMPORTED_MODULE_16__.RxDBMigrationSchemaPlugin); (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_update__WEBPACK_IMPORTED_MODULE_17__.RxDBUpdatePlugin); if (devMode) (0,rxdb__WEBPACK_IMPORTED_MODULE_8__.addRxPlugin)(rxdb_plugins_dev_mode__WEBPACK_IMPORTED_MODULE_13__.RxDBDevModePlugin); } static ɵfac = function RxdbManager_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RxdbManager)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: RxdbManager, factory: RxdbManager.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 86515 /*!**********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/index.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MIGRATION_STRATEGIES: () => (/* binding */ MIGRATION_STRATEGIES), /* harmony export */ applyMigrations: () => (/* binding */ applyMigrations) /* harmony export */ }); /* harmony import */ var _v1__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./v1 */ 93066); /* harmony import */ var _v2__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./v2 */ 69583); /* harmony import */ var _v3__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./v3 */ 30560); /* harmony import */ var _v4__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./v4 */ 73133); /* harmony import */ var _v5__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./v5 */ 438); /* harmony import */ var _v6__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./v6 */ 35531); /* harmony import */ var _v7__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./v7 */ 12204); /* harmony import */ var _v8__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./v8 */ 83577); /* harmony import */ var _v9__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./v9 */ 338); /* harmony import */ var _v10__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./v10 */ 43744); /* harmony import */ var _v11__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./v11 */ 24783); /* harmony import */ var _v12__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./v12 */ 65674); /* harmony import */ var _v13__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./v13 */ 7985); /* harmony import */ var _v14__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./v14 */ 19500); /* harmony import */ var _v15__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./v15 */ 48715); /* harmony import */ var _v16__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./v16 */ 7222); /* harmony import */ var _v17__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./v17 */ 51226); /* harmony import */ var _v18__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./v18 */ 99912); /* harmony import */ var _v19__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./v19 */ 27543); /* harmony import */ var _v20__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./v20 */ 89371); /* harmony import */ var _v21__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./v21 */ 59900); /* harmony import */ var _v22__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./v22 */ 69245); /* harmony import */ var _v23__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./v23 */ 12646); /* harmony import */ var _v24__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./v24 */ 42399); /* harmony import */ var _v25__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./v25 */ 84400); /* harmony import */ var _v26__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./v26 */ 48385); /* harmony import */ var _v27__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./v27 */ 83034); // For documents pulled from the backend — RxDB only migrates locally stored // documents. Returns null when a strategy drops the document (e.g. pre-store // sessions at v19). function applyMigrations(document, fromVersion, toVersion) { let migrated = document; for (let version = fromVersion + 1; version <= toVersion && migrated; version++) { const strategy = MIGRATION_STRATEGIES[version]; if (!strategy) { throw new Error(`No work-session migration strategy for v${version}`); } migrated = strategy(migrated); } return migrated; } const MIGRATION_STRATEGIES = { 1: _v1__WEBPACK_IMPORTED_MODULE_0__.migrateToV1, 2: _v2__WEBPACK_IMPORTED_MODULE_1__.migrateToV2, 3: _v3__WEBPACK_IMPORTED_MODULE_2__.migrateToV3, 4: _v4__WEBPACK_IMPORTED_MODULE_3__.migrateToV4, 5: _v5__WEBPACK_IMPORTED_MODULE_4__.migrateToV5, 6: _v6__WEBPACK_IMPORTED_MODULE_5__.migrateToV6, 7: _v7__WEBPACK_IMPORTED_MODULE_6__.migrateToV7, 8: _v8__WEBPACK_IMPORTED_MODULE_7__.migrateToV8, 9: _v9__WEBPACK_IMPORTED_MODULE_8__.migrateToV9, 10: _v10__WEBPACK_IMPORTED_MODULE_9__.migrateToV10, 11: _v11__WEBPACK_IMPORTED_MODULE_10__.migrateToV11, 12: _v12__WEBPACK_IMPORTED_MODULE_11__.migrateToV12, 13: _v13__WEBPACK_IMPORTED_MODULE_12__.migrateToV13, 14: _v14__WEBPACK_IMPORTED_MODULE_13__.migrateToV14, 15: _v15__WEBPACK_IMPORTED_MODULE_14__.migrateToV15, 16: _v16__WEBPACK_IMPORTED_MODULE_15__.migrateToV16, 17: _v17__WEBPACK_IMPORTED_MODULE_16__.migrateToV17, 18: _v18__WEBPACK_IMPORTED_MODULE_17__.migrateToV18, 19: _v19__WEBPACK_IMPORTED_MODULE_18__.migrateToV19, 20: _v20__WEBPACK_IMPORTED_MODULE_19__.migrateToV20, 21: _v21__WEBPACK_IMPORTED_MODULE_20__.migrateToV21, 22: _v22__WEBPACK_IMPORTED_MODULE_21__.migrateToV22, 23: _v23__WEBPACK_IMPORTED_MODULE_22__.migrateToV23, 24: _v24__WEBPACK_IMPORTED_MODULE_23__.migrateToV24, 25: _v25__WEBPACK_IMPORTED_MODULE_24__.migrateToV25, 26: _v26__WEBPACK_IMPORTED_MODULE_25__.migrateToV26, 27: _v27__WEBPACK_IMPORTED_MODULE_26__.migrateToV27 }; /***/ }, /***/ 93066 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v1.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV1: () => (/* binding */ migrateToV1) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); /* harmony import */ var _tomoverse_utils_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils/dicom/windowing-presets */ 21423); /* harmony import */ var _tomoverse_utils_volume_viewer_map_viewport_to_orientation__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils/volume-viewer/map-viewport-to-orientation */ 3009); const migrateToV1 = oldDocument => ({ ...oldDocument, name: `${_tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.ANALYSIS_BASE_NAME} 1`, schemaVersion: 1, viewportStates: oldDocument.viewportStates.map(viewportState => ({ ...viewportState, axialPlane: viewportState.AX, cameraState: undefined, coronalPlane: viewportState.CC, fieldOfView: viewportState.FOV, isDarkMode: false, isPosterior: false, orientation: viewportState.orientation ?? (0,_tomoverse_utils_volume_viewer_map_viewport_to_orientation__WEBPACK_IMPORTED_MODULE_3__.mapViewportIdToOrientation)(viewportState.viewportId), sagittalPlane: viewportState.RL, type: viewportState.type ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportType.ORTHOGRAPHIC, windowPresetName: viewportState.windowPresetName ?? `${_tomoverse_utils_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_2__.PRESET_NAME_PREFIX} ${new Date().toISOString()}` })) }); /***/ }, /***/ 43744 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v10.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV10: () => (/* binding */ migrateToV10) /* harmony export */ }); // An enum was modified between V9-V10 with values that weren't previous // used, so this migration is basically a no-op const migrateToV10 = oldDocument => { return { ...oldDocument, schemaVersion: 10 }; }; /***/ }, /***/ 24783 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v11.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV11: () => (/* binding */ migrateToV11) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const migrateToV11 = oldDocument => { return { ...oldDocument, annotations: // eslint-disable-next-line @typescript-eslint/no-explicit-any oldDocument.annotations?.map(annotation => { // Previously used `uid` const newAnnotation = { ...annotation, id: annotation.uid }; delete newAnnotation.uid; // Previously converted `position` to `points[0]` if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT) { newAnnotation.position = annotation.points[0]; delete newAnnotation.points; } return newAnnotation; }) ?? [], schemaVersion: 11 }; }; /***/ }, /***/ 65674 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v12.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV12: () => (/* binding */ migrateToV12) /* harmony export */ }); // The only difference between V11-V12 is enabling attachments // and adding new fields to some annotation types, // so this migration is basically a no-op const migrateToV12 = oldDocument => { return { ...oldDocument, schemaVersion: 12 }; }; /***/ }, /***/ 7985 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v13.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV13: () => (/* binding */ migrateToV13) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const DEFAULT_VASCULAR_PRESET = { ambient: 0.27, bloodCalciumThreshold: 1000, clusterSize: 10_000, diffuse: 0.84, distalDepth: -150, erosionRadius: 2, gridStep: 15, hasAcceptedSegmentation: false, imageQuality: 70, label: 'Vascular', maxHU: 1000, minHU: 170, opacityTransitionWidth: 1, outlierOpacity: 0, proximalDepth: 150, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR, specular: 0.4, specularPower: 20, tissueBloodThreshold: 170 }; // Vascular preset introduced with segmentation fields in V13. // Also inserts the full default vascular preset for sessions created before vascular mode existed. const migrateToV13 = oldDocument => { const presets = oldDocument.renderSettings.volumeRenderPresets; const hasVascular = presets.some(p => p.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR); const updatedPresets = presets.map(preset => { if (preset.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR) return preset; return { clusterSize: 10_000, erosionRadius: 2, gridStep: 15, hasAcceptedSegmentation: false, maxHU: 1000, minHU: 170, outlierOpacity: 0, ...preset }; }); return { ...oldDocument, renderSettings: { ...oldDocument.renderSettings, volumeRenderPresets: hasVascular ? updatedPresets : [...updatedPresets, DEFAULT_VASCULAR_PRESET] }, schemaVersion: 13 }; }; /***/ }, /***/ 19500 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v14.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV14: () => (/* binding */ migrateToV14) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const OBJECT3D_TYPES = new Set([_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CYLINDER, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.HOLLOW_CYLINDER, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.STL]); // V13 → V14 adds `locked` (all Object3D types) and optional `centerOfRotation` (STL). // Backfill `locked: false` on pre-existing 3D objects; `centerOfRotation` stays // unset and falls back to the mesh centroid at render time. const migrateToV14 = oldDocument => ({ ...oldDocument, annotations: // eslint-disable-next-line @typescript-eslint/no-explicit-any oldDocument.annotations?.map(annotation => OBJECT3D_TYPES.has(annotation.type) && annotation.locked === undefined ? { ...annotation, locked: false } : annotation) ?? [], schemaVersion: 14 }); /***/ }, /***/ 48715 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v15.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV15: () => (/* binding */ migrateToV15) /* harmony export */ }); // Ensure the `protocols` section is added to documents const migrateToV15 = oldDocument => ({ ...oldDocument, protocols: { definitions: [], instances: [] }, schemaVersion: 15 }); /***/ }, /***/ 7222 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v16.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV16: () => (/* binding */ migrateToV16) /* harmony export */ }); // `storeUid` is required (store-scoped viewer). Pre-store sessions can't target a // store, so drop them (return null). A fresh session is created when reopened. const migrateToV16 = oldDocument => // eslint-disable-next-line unicorn/no-null oldDocument.storeUid ? { ...oldDocument, schemaVersion: 16 } : null; /***/ }, /***/ 51226 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v17.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV17: () => (/* binding */ migrateToV17) /* harmony export */ }); // Split the V16 "protocols" property so that the protocol definitions // are in the top-level worksession, and the instances are in the volume const migrateToV17 = oldDocument => { // V16 may have dropped the document (returned null for a pre-store session). // Propagate that instead of dereferencing a null document. if (!oldDocument) return oldDocument; return { ...oldDocument, protocolDefinitions: oldDocument.protocols?.definitions ?? [], schemaVersion: 17, volumes: oldDocument.volumes.map((volume, index) => ({ ...volume, protocolData: index === 0 ? { instances: oldDocument.protocols?.instances ?? [] } : { instances: [] } })) }; }; /***/ }, /***/ 99912 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v18.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV18: () => (/* binding */ migrateToV18) /* harmony export */ }); // V17 → V18: clamp stored vascular slab depths and imageQuality to the new faster // defaults, preserving tighter user-chosen values. Literals are historical snapshots, // not references to the live constants. const VASCULAR_PRESET_NAME = 'CT-Vascular'; const MAX_PROXIMAL_DEPTH = 75; const MIN_DISTAL_DEPTH = -75; const MAX_IMAGE_QUALITY = 50; const clampVascularPreset = preset => { if (preset?.selectedPreset !== VASCULAR_PRESET_NAME) return preset; const next = { ...preset }; if (typeof next.proximalDepth === 'number') { next.proximalDepth = Math.min(next.proximalDepth, MAX_PROXIMAL_DEPTH); } if (typeof next.distalDepth === 'number') { next.distalDepth = Math.max(next.distalDepth, MIN_DISTAL_DEPTH); } if (typeof next.imageQuality === 'number') { next.imageQuality = Math.min(next.imageQuality, MAX_IMAGE_QUALITY); } return next; }; const clampRenderSettings = renderSettings => { if (!renderSettings?.volumeRenderPresets) return renderSettings; return { ...renderSettings, volumeRenderPresets: renderSettings.volumeRenderPresets.map(preset => clampVascularPreset(preset)) }; }; const migrateToV18 = oldDocument => { const document = oldDocument; return { ...document, renderSettings: clampRenderSettings(document.renderSettings), schemaVersion: 18, volumes: (document.volumes ?? []).map(volume => ({ ...volume, renderSettings: clampRenderSettings(volume.renderSettings) })) }; }; /***/ }, /***/ 27543 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v19.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV19: () => (/* binding */ migrateToV19) /* harmony export */ }); // `storeUid` is required (store-scoped viewer). Pre-store sessions can't target a // store, so drop them (return null). A fresh session is created when reopened. const migrateToV19 = oldDocument => // eslint-disable-next-line unicorn/no-null oldDocument.storeUid ? { ...oldDocument, schemaVersion: 19 } : null; /***/ }, /***/ 69583 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v2.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV2: () => (/* binding */ migrateToV2) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); const migrateToV2 = oldDocument => ({ ...oldDocument, name: `${_tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.ANALYSIS_BASE_NAME} 2`, renderSettings: { forceLowQuality: false, selectedWindowPresetName: 'window1', volumeSettings: { ..._tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO] }, windowPresets: [] // Will be populated on first load }, schemaVersion: 2, viewportCamera: { ax: 0, cameraDistance: -10, intersection: [0, 0, 0], isocenter: [0, 0, 0], isPosterior: false, matrix: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.INIT_CAMERA_MATRIX, showCrosshairs: true, viewportAxisMapping: { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.ALTERNATEBOTTOMLEFT]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.ALTERNATETOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.BOTTOMLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.MIDDLEMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.RIGHTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.TOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxis.AXIAL }, zoom: 1 } }); /***/ }, /***/ 89371 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v20.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV20: () => (/* binding */ migrateToV20) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); // V19 → V20: adds vascularThresholdsAutoTuned so the histogram auto-tune heuristic can // tell "never touched" apart from "reset back to the default values" — pre-V20 sessions // already have real (possibly user-set) thresholds, so they must be marked as tuned // rather than left eligible for the heuristic to silently overwrite them. Also adds // vascularSegmentationState so the segmentation mode (none/previewing/applied) is // persisted alongside the thresholds it now governs — derived from the already-persisted // hasAcceptedSegmentation flag rather than defaulting everyone to "none". const backfillVascularPreset = preset => { if (preset?.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR) return preset; return { vascularSegmentationState: preset.hasAcceptedSegmentation ? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VascularSegmentationState.APPLIED : _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VascularSegmentationState.NONE, vascularThresholdsAutoTuned: true, ...preset }; }; const backfillRenderSettings = renderSettings => { if (!renderSettings?.volumeRenderPresets) return renderSettings; return { ...renderSettings, volumeRenderPresets: renderSettings.volumeRenderPresets.map(preset => backfillVascularPreset(preset)) }; }; const migrateToV20 = oldDocument => { const document = oldDocument; return { ...document, renderSettings: backfillRenderSettings(document.renderSettings), schemaVersion: 20, volumes: (document.volumes ?? []).map(volume => ({ ...volume, renderSettings: backfillRenderSettings(volume.renderSettings) })) }; }; /***/ }, /***/ 59900 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v21.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV21: () => (/* binding */ migrateToV21) /* harmony export */ }); // V20 → V21: backfills chambers on each volume. Pre-V21 local documents predate the // chambers field entirely, so without this they fail workSessionSchema validation on load. const migrateToV21 = oldDocument => { const document = oldDocument; return { ...document, schemaVersion: 21, volumes: (document.volumes ?? []).map(volume => ({ ...volume, chambers: volume.chambers ?? [] })) }; }; /***/ }, /***/ 69245 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v22.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV22: () => (/* binding */ migrateToV22) /* harmony export */ }); // Matches DEFAULT_S_CURVE_LINE_WIDTH in @tomoverse/dtos and the default `fontSize` // on ScaleComponent in @tomoverse/ui - the values these fields replace as hardcoded // constants. const DEFAULT_S_CURVE_LINE_WIDTH = 2; const DEFAULT_S_CURVE_GRAPH_FONT_SIZE = 9; // V21 → V22: backfills sCurves/sCurveRelativeMeasurements on each volume (with // per-curve `lineWidth`), and `sCurveGraphFontSize` on every renderSettings object // (root + per-volume). Pre-V22 local documents predate all of these fields entirely, // so without this they fail workSessionSchema validation on load. const migrateToV22 = oldDocument => { const document = oldDocument; const backfillRenderSettings = renderSettings => ({ ...renderSettings, sCurveGraphFontSize: renderSettings?.['sCurveGraphFontSize'] ?? DEFAULT_S_CURVE_GRAPH_FONT_SIZE }); return { ...document, renderSettings: backfillRenderSettings(document.renderSettings), schemaVersion: 22, volumes: (document.volumes ?? []).map(volume => ({ ...volume, renderSettings: backfillRenderSettings(volume.renderSettings), sCurveRelativeMeasurements: volume.sCurveRelativeMeasurements ?? [], sCurves: (volume.sCurves ?? []).map(sCurve => ({ ...sCurve, lineWidth: sCurve.lineWidth ?? DEFAULT_S_CURVE_LINE_WIDTH })) })) }; }; /***/ }, /***/ 12646 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v23.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV23: () => (/* binding */ migrateToV23) /* harmony export */ }); // Matches DEFAULT_S_CURVE_LINE_WIDTH in @tomoverse/dtos - line width moved from a // per-curve field to a single graph-wide renderSettings field (see DEFAULT_S_CURVE_GRAPH_FONT_SIZE // for the same pattern, backfilled in v22). const DEFAULT_S_CURVE_LINE_WIDTH = 2; // Pre-V23 documents have no single "the" line width - each curve could have its own. Take the // first explicit value found (volume order, then curve order) as the new graph-wide default, // rather than silently discarding every curve's customization in favor of the hardcoded default. function findLegacyLineWidth(volumes) { for (const volume of volumes) { for (const sCurve of volume.sCurves ?? []) { if (typeof sCurve.lineWidth === 'number') return sCurve.lineWidth; } } return undefined; } // V22 → V23: backfills `sCurveLineWidth` on every renderSettings object (root + per-volume), // deriving it from any legacy per-curve `lineWidth` when present so existing customization // isn't lost. Pre-V23 local documents predate this field, so without this they fail // workSessionSchema validation on load. Also strips the now-obsolete per-curve `lineWidth` - // `additionalProperties: false` on the sCurve schema means AJV rejects any document that still // carries it, which would otherwise fail migration for real users' existing curves. const migrateToV23 = oldDocument => { const document = oldDocument; const legacyLineWidth = findLegacyLineWidth(document.volumes ?? []); const defaultLineWidth = legacyLineWidth ?? DEFAULT_S_CURVE_LINE_WIDTH; const backfillRenderSettings = renderSettings => ({ ...renderSettings, sCurveLineWidth: renderSettings?.['sCurveLineWidth'] ?? defaultLineWidth }); return { ...document, renderSettings: backfillRenderSettings(document.renderSettings), schemaVersion: 23, volumes: (document.volumes ?? []).map(volume => ({ ...volume, renderSettings: backfillRenderSettings(volume.renderSettings), sCurves: (volume.sCurves ?? []).map(({ lineWidth, ...sCurve }) => sCurve) })) }; }; /***/ }, /***/ 42399 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v24.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV24: () => (/* binding */ migrateToV24) /* harmony export */ }); // Matches DEFAULT_S_CURVE_LINE_WIDTH's sibling pattern - `ax` (the viewport rotation slider // value) moved onto each chamber so "go to chamber" can restore it, alongside cameraOrientation. const DEFAULT_CHAMBER_AX = 0; // V23 → V24: backfills `ax` on each chamber. Pre-V24 local documents predate this field, so // without this they fail workSessionSchema validation on load. const migrateToV24 = oldDocument => { const document = oldDocument; return { ...document, schemaVersion: 24, volumes: (document.volumes ?? []).map(volume => ({ ...volume, chambers: (volume.chambers ?? []).map(chamber => ({ ...chamber, ax: chamber.ax ?? DEFAULT_CHAMBER_AX })) })) }; }; /***/ }, /***/ 84400 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v25.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV25: () => (/* binding */ migrateToV25) /* harmony export */ }); // V24 → V25: adds `isocenter`, `intersection`, and `crosshairRotation` to the chamber schema. // These are optional rather than backfilled - pre-V25 chambers never captured this state, so // there's no real value to fill in, and "go to chamber" skips restoring them when absent // instead of snapping to a fabricated position. No document rewriting is needed; only the // version bumps. const migrateToV25 = oldDocument => { return { ...oldDocument, schemaVersion: 25 }; }; /***/ }, /***/ 48385 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v26.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV26: () => (/* binding */ migrateToV26) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const MIP_PRESET = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.MIP]; const backfillMipPreset = renderSettings => { if (!renderSettings?.volumeRenderPresets) return renderSettings; const hasMipPreset = renderSettings.volumeRenderPresets.some(preset => preset.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.MIP); if (hasMipPreset) return renderSettings; return { ...renderSettings, volumeRenderPresets: [...renderSettings.volumeRenderPresets, MIP_PRESET] }; }; // V25 -> V26: MIP was added as a volume-rendering preset. Pre-V26 sessions already // have persisted preset arrays, so append the default MIP preset without overwriting any // user-customized MIP preset that may already exist. const migrateToV26 = oldDocument => { const document = oldDocument; return { ...document, renderSettings: backfillMipPreset(document.renderSettings), schemaVersion: 26, volumes: document.volumes?.map(volume => ({ ...volume, renderSettings: backfillMipPreset(volume.renderSettings) })) }; }; /***/ }, /***/ 83034 /*!********************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v27.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV27: () => (/* binding */ migrateToV27) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); const rewriteProtocolData = protocolData => { if (!protocolData) return protocolData; return { ...protocolData, ...(typeof protocolData.activeProtocolId === 'string' ? { activeProtocolId: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.canonicalProtocolId)(protocolData.activeProtocolId) } : {}), ...(protocolData.instances ? { instances: protocolData.instances.map(instance => typeof instance.protocolId === 'string' ? { ...instance, protocolId: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.canonicalProtocolId)(instance.protocolId) } : instance) } : {}) }; }; // V26 -> V27: the TAVI protocol id was aligned with the annotation manual. The id is a primary // key across protocolDefinitions, protocolData.activeProtocolId and every instance's protocolId, // so all three are rewritten together - a partial rewrite would orphan the instances from their // definition. Non-TAVI ids pass through untouched. const migrateToV27 = oldDocument => { const document = oldDocument; return { ...document, protocolDefinitions: document.protocolDefinitions?.map(definition => typeof definition.id === 'string' ? { ...definition, id: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.canonicalProtocolId)(definition.id) } : definition), schemaVersion: 27, volumes: document.volumes?.map(volume => ({ ...volume, protocolData: rewriteProtocolData(volume.protocolData) })) }; }; /***/ }, /***/ 30560 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v3.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV3: () => (/* binding */ migrateToV3) /* harmony export */ }); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); const migrateToV3 = oldDocument => ({ ...oldDocument, name: `${_tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_0__.ANALYSIS_BASE_NAME} 3`, renderSettings: { forceLowQuality: false, selectedVolumePresetName: 'CT-Cardiac3', selectedWindowPresetName: 'window1', volumeRenderPresets: [], // Will be populated on first load windowPresets: [] // Will be populated on first load }, schemaVersion: 3 }); /***/ }, /***/ 73133 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v4.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV4: () => (/* binding */ migrateToV4) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); const migrateToV4 = oldDocument => ({ ...oldDocument, renderSettings: { ...oldDocument.renderSettings, volumeRenderPresets: oldDocument.renderSettings.volumeRenderPresets.map(preset => { switch (preset.value) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO: { return { airTissueThreshold: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO].airTissueThreshold, bloodCalciumThreshold: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO].bloodCalciumThreshold, distalDepth: preset.distalDepth, imageQuality: preset.imageQuality, label: preset.label, proximalDepth: preset.proximalDepth, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO, tissueBloodThreshold: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO].tissueBloodThreshold }; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.FLUOROSCOPIC: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.XRAY: { const { value, ...rest } = preset; return { ...rest, selectedPreset: value }; } } }) }, schemaVersion: 4 }); /***/ }, /***/ 438 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v5.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV5: () => (/* binding */ migrateToV5) /* harmony export */ }); // Only optional fields were added between V4-V5, so this migration // is basically a no-op; const migrateToV5 = oldDocument => { return { ...oldDocument, schemaVersion: 5 }; }; /***/ }, /***/ 35531 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v6.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV6: () => (/* binding */ migrateToV6) /* harmony export */ }); // An enum was modified between V5-V6 with values that weren't previous // used, so this migration is basically a no-op const migrateToV6 = oldDocument => { return { ...oldDocument, schemaVersion: 6 }; }; /***/ }, /***/ 12204 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v7.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV7: () => (/* binding */ migrateToV7) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); const ENDO_DEFAULTS = _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_1__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO]; const migrateToV7 = oldDocument => { if (!oldDocument.renderSettings) return oldDocument; return { ...oldDocument, renderSettings: { ...oldDocument.renderSettings, volumeRenderPresets: oldDocument.renderSettings.volumeRenderPresets.map(preset => { if (preset.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO) return preset; return { ...ENDO_DEFAULTS, ...preset }; }) }, schemaVersion: 7 }; }; /***/ }, /***/ 83577 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v8.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV8: () => (/* binding */ migrateToV8) /* harmony export */ }); const migrateToV8 = oldDocument => ({ ...oldDocument, annotationSize: 2, schemaVersion: 8 }); /***/ }, /***/ 338 /*!*******************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/migrations/v9.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ migrateToV9: () => (/* binding */ migrateToV9) /* harmony export */ }); // An enum was modified between V8-V9 with values that weren't previous // used, so this migration is basically a no-op const migrateToV9 = oldDocument => { return { ...oldDocument, schemaVersion: 9 }; }; /***/ }, /***/ 17818 /*!***********************************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/work-session-database.service.ts ***! \***********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionDatabaseService: () => (/* binding */ WorkSessionDatabaseService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 90015); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 8102); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxdb */ 73738); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../rxdb-attachment-binary */ 94669); /* harmony import */ var _services_work_session_work_session_api_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../services/work-session/work-session-api.service */ 29039); /* harmony import */ var _rxdb_manager_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../rxdb-manager.service */ 67189); /* harmony import */ var _work_session_collection__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./work-session.collection */ 32159); class WorkSessionDatabaseService { rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_11__.RxdbManager); workSessionApi = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_work_session_work_session_api_service__WEBPACK_IMPORTED_MODULE_10__.WorkSessionApiService); find() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (filters = {}) { const collection = yield _this.rxdbManager.getWorkSessionCollection(); const documents = yield collection.find({ selector: filters }).exec(); return documents.map(workSessionDocument => workSessionDocument.toJSON()); }).apply(this, arguments); } get(uid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this2.rxdbManager.getWorkSessionCollection(); const workSessionDocument = yield collection.findOne(uid).exec(); return workSessionDocument?.toJSON(); })(); } getAttachments(uid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this3.rxdbManager.getWorkSessionCollection(); const workSessionDocument = yield collection.findOne(uid).exec(); return workSessionDocument?.allAttachments(); })(); } get$(uid) { return this.rxdbManager.workSessions$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.switchMap)(collection => collection ? collection.findOne(uid).$ : rxjs__WEBPACK_IMPORTED_MODULE_3__.EMPTY), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.map)(workSessionDocument => workSessionDocument?.toJSON()), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.distinctUntilChanged)(rxdb__WEBPACK_IMPORTED_MODULE_8__.deepEqual)); } workSessions$(filters = {}) { return this.rxdbManager.workSessions$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.switchMap)(collection => { if (!collection) return rxjs__WEBPACK_IMPORTED_MODULE_3__.EMPTY; return collection.find({ selector: filters }).$; }), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.map)(documents => documents.map(workSessionDocument => workSessionDocument.toJSON()))); } syncWorkSessionsFromServer(collection, filters) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const serverWorkSessions = yield _this4.workSessionApi.find(filters); if (serverWorkSessions.length === 0) return; const ids = serverWorkSessions.map(({ uid }) => uid); const existingDocuments = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.firstValueFrom)(collection.findByIds(ids).$); // Only update work sessions that have actually changed - otherwise the // `collection.preSave()` hook will update the `updatedAt` timestamp // on every work session fetched const changed = serverWorkSessions.filter(session => { const existing = existingDocuments.get(session.uid); if (!existing) return true; return existing.version < session.version; }); // We populate the each work session's attachments in a separate http call // because doing so in a batch call could hit response size limits const withAttachments = yield Promise.all(changed.map(session => _this4.ensureAttachments(session))); yield collection.bulkUpsert(withAttachments, { deleteExistingAttachments: false }); } catch (error) { console.error('Failed to refresh work sessions from server', error); } })(); } ensureAttachments(session) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // If there are no attachments for this work session, nothing else to do if (Object.keys(session._attachments).length === 0) { return session; } // Otherwise, fetch the full attachment data from the backend. try { const withAttachments = yield _this5.workSessionApi.get(session.uid, true); for (const attachment of Object.values(withAttachments._attachments)) { if (attachment.data) { // eslint-disable-next-line @typescript-eslint/no-explicit-any attachment.data = (0,_rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_9__.toRxdbAttachmentBinary)((0,rxdb__WEBPACK_IMPORTED_MODULE_7__.base64ToArrayBuffer)(attachment.data)); } } return withAttachments; } catch (error) { console.warn('Failed to fetch workSession attachments', error); return session; } })(); } save(_x) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (workSession, { attachments, incrementVersion } = {}) { const collection = yield _this6.rxdbManager.getWorkSessionCollection(); const update = { ...workSession, _attachments: attachments ? [...attachments] : undefined, version: incrementVersion ? workSession.version + 1 : workSession.version }; yield collection.incrementalUpsert(update, { deleteExistingAttachments: attachments !== undefined }); }).apply(this, arguments); } addAttachment(workSessionId, creator) { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this7.rxdbManager.getWorkSessionCollection(); const document = yield collection.findOne(workSessionId).exec(); yield document?.putAttachment(creator); })(); } delete(uid) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this8.rxdbManager.getWorkSessionCollection(); const workSessionDocument = yield collection.findOne(uid).exec(); if (workSessionDocument) { yield workSessionDocument.incrementalRemove(); } })(); } markDraft(uid) { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this9.rxdbManager.getWorkSessionCollection(); yield collection.upsertLocal((0,_work_session_collection__WEBPACK_IMPORTED_MODULE_12__.workSessionDraftKey)(uid), { draft: true }); })(); } clearDraft(uid) { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this0.rxdbManager.getWorkSessionCollection(); // Flip rather than remove: the push handler must see the finalization to // re-send attachment data its dropped draft-era pushes never delivered. yield collection.upsertLocal((0,_work_session_collection__WEBPACK_IMPORTED_MODULE_12__.workSessionDraftKey)(uid), { draft: false }); })(); } isDraft(uid) { var _this1 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const collection = yield _this1.rxdbManager.getWorkSessionCollection(); const marker = yield collection.getLocal((0,_work_session_collection__WEBPACK_IMPORTED_MODULE_12__.workSessionDraftKey)(uid)); return !!marker?.get('draft'); })(); } static ɵfac = function WorkSessionDatabaseService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionDatabaseService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: WorkSessionDatabaseService, factory: WorkSessionDatabaseService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 32159 /*!*****************************************************************************!*\ !*** ./libs/data-access/src/lib/db/work-session/work-session.collection.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ createWorkSessionPullHandler: () => (/* binding */ createWorkSessionPullHandler), /* harmony export */ createWorkSessionPushHandler: () => (/* binding */ createWorkSessionPushHandler), /* harmony export */ prepareIncomingWorkSession: () => (/* binding */ prepareIncomingWorkSession), /* harmony export */ setupWorkSessionCollection: () => (/* binding */ setupWorkSessionCollection), /* harmony export */ workSessionDraftKey: () => (/* binding */ workSessionDraftKey) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxdb */ 64062); /* harmony import */ var rxdb_plugins_replication__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxdb/plugins/replication */ 9350); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_utils_pipes_exponential_backoff_pipe__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/utils/pipes/exponential-backoff.pipe */ 4251); /* harmony import */ var _rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../rxdb-attachment-binary */ 94669); /* harmony import */ var _services_work_session_work_session_sse_client__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../services/work-session/work-session-sse-client */ 99335); /* harmony import */ var _migrations__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./migrations */ 86515); const workSessionDraftKey = uid => `draft-${uid}`; // RxDB records rows the handler drops as delivered, so pushes after finalization // omit the attachment data it believes the backend already has. Refill it from // local storage for this one push. const refillAttachmentData = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (collection, row) { const attachments = Object.entries(row.newDocumentState._attachments ?? {}); if (attachments.length === 0) return; const workSessionDocument = yield collection.findOne(row.newDocumentState.uid).exec(); if (!workSessionDocument) return; for (const [id, attachment] of attachments) { if ('data' in attachment && attachment.data) continue; const stored = workSessionDocument.getAttachment(id); if (!stored) continue; attachment.data = yield stored.getDataBase64(); } }); return function refillAttachmentData(_x, _x2) { return _ref.apply(this, arguments); }; }(); // Never-saved sessions stay off the backend. const partitionDraftRows = /*#__PURE__*/function () { var _ref2 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (collection, documents) { const pushable = []; const finalizedMarkers = []; for (const document of documents) { const uid = document.newDocumentState.uid; const marker = yield collection.getLocal(workSessionDraftKey(uid)); if (marker?.get('draft')) continue; if (marker) { yield refillAttachmentData(collection, document); finalizedMarkers.push({ marker, uid }); } pushable.push(document); } return { finalizedMarkers, pushable }; }); return function partitionDraftRows(_x3, _x4) { return _ref2.apply(this, arguments); }; }(); const createWorkSessionPushHandler = (collection, http, syncUrl) => (/*#__PURE__*/function () { var _ref3 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (documents) { const { finalizedMarkers, pushable } = yield partitionDraftRows(collection, documents); if (pushable.length === 0) return []; for (const document of pushable) { for (const attachment of Object.values(document.newDocumentState._attachments ?? {})) { // Can't directly serialize Blobs if ('data' in attachment && attachment.data instanceof Blob) { // eslint-disable-next-line @typescript-eslint/no-explicit-any attachment.data = yield (0,rxdb__WEBPACK_IMPORTED_MODULE_6__.blobToBase64String)(attachment.data); } } } const conflicts = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.firstValueFrom)(http.post(`${syncUrl}/push`, pushable)); // Only for accepted documents: failed or conflicted pushes retry and must refill again. const conflictUids = new Set(conflicts.map(({ uid }) => uid)); for (const { marker, uid } of finalizedMarkers) { if (!conflictUids.has(uid)) yield marker.remove(); } return conflicts; }); return function (_x5) { return _ref3.apply(this, arguments); }; }()); // Migrates, normalizes and validates a document arriving from the backend. // Returns undefined to skip it: one rejected document would otherwise fail the // whole replication batch and stall the sync for good. const prepareIncomingWorkSession = workSession => { if (workSession._deleted) return workSession; let document = workSession; if (document.schemaVersion < _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_8__.WORK_SESSION_LATEST_SCHEMA) { try { const migrated = (0,_migrations__WEBPACK_IMPORTED_MODULE_12__.applyMigrations)(document, document.schemaVersion, _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_8__.WORK_SESSION_LATEST_SCHEMA); if (!migrated) return undefined; document = migrated; } catch (error) { console.warn('Failed to migrate work session', workSession.uid, error); return undefined; } } try { const normalized = { ...document, _attachments: Object.fromEntries(Object.entries(document._attachments ?? {}).map(([id, attachment]) => [id, { ...attachment, data: 'data' in attachment && (0,_ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.isString)(attachment.data) ? base64ToBlob(attachment.data) : undefined }])), volumes: document.volumes?.map(volume => ({ ...volume, annotations: volume.annotations?.map(annotation => ({ ...annotation, placeholderId: annotation.placeholderId ?? undefined })), chambers: volume.chambers ?? [] })) }; const { _attachments, _deleted, ...content } = normalized; const validation = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_8__.workSessionSchema.safeParse(content); if (!validation.success) { console.warn('Skipping invalid work session', workSession.uid, validation.error); return undefined; } return normalized; } catch (error) { console.warn('Skipping invalid work session', workSession.uid, error); return undefined; } }; const prepareIncomingWorkSessions = documents => documents.map(document => prepareIncomingWorkSession(document)).filter(document => document !== undefined); // A short batch tells RxDB it is fully synced, so dropped documents must not shrink the batch. const createWorkSessionPullHandler = (http, syncUrl) => (/*#__PURE__*/function () { var _ref4 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (lastCheckpoint, batchSize) { let checkpoint = lastCheckpoint; const prepared = []; for (;;) { const documents = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.firstValueFrom)(http.get(`${syncUrl}/pull`, { params: { lastUpdatedAt: (checkpoint?.lastUpdatedAt ?? 0).toString(), limit: batchSize.toString() } })); // Checkpoint from the raw batch, so skipped documents aren't re-pulled forever. const last = documents.at(-1); if (last) checkpoint = { lastUpdatedAt: last.updatedAt }; prepared.push(...prepareIncomingWorkSessions(documents)); if (documents.length < batchSize || prepared.length >= batchSize) { return { checkpoint, documents: prepared }; } } }); return function (_x6, _x7) { return _ref4.apply(this, arguments); }; }()); function setupWorkSessionCollection(_x8, _x9, _x0, _x1) { return _setupWorkSessionCollection.apply(this, arguments); } function _setupWorkSessionCollection() { _setupWorkSessionCollection = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (database, http, authService, apiUrl) { const updatedDatabase = yield database.addCollections({ workSession: { conflictHandler: { isEqual: (a, b) => a.updatedAt === b.updatedAt, resolve: function () { var _ref5 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({ realMasterState }) { return realMasterState; }); return function resolve(_x10) { return _ref5.apply(this, arguments); }; }() }, localDocuments: true, migrationStrategies: _migrations__WEBPACK_IMPORTED_MODULE_12__.MIGRATION_STRATEGIES, schema: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_8__.workSessionRxdbJsonSchema } }); const { workSession: collection } = updatedDatabase; const syncUrl = `${apiUrl}/work-session/sync`; const sseClient = new _services_work_session_work_session_sse_client__WEBPACK_IMPORTED_MODULE_11__.WorkSessionSseClient(); collection.preInsert(data => { const userId = authService.currentUser()?.accountId; if (!userId) throw new Error('Authentication required'); const now = new Date().toISOString(); data.createdAt = now; data.createdByUid = userId; data.updatedAt = now; data.updatedByUid = userId; }, true); collection.preSave(data => { const userId = authService.currentUser()?.accountId; if (!userId) throw new Error('Authentication required'); data.updatedAt = new Date().toISOString(); data.updatedByUid = userId; }, true); const replicationState = (0,rxdb_plugins_replication__WEBPACK_IMPORTED_MODULE_7__.replicateRxCollection)({ collection, pull: { handler: createWorkSessionPullHandler(http, syncUrl), stream$: sseClient.stream(`${syncUrl}/stream`, { authProbe: function () { var _ref6 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // We start stream calls with this so that the // AuthInterceptor can refresh tokens / log out if necessary. try { yield (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.firstValueFrom)(authService.fetchUser()); } catch (error) { yield authService.logout(); throw error; } }); return function authProbe() { return _ref6.apply(this, arguments); }; }(), getToken: () => authService.getAccessToken(), keepAlive: true }).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_4__.map)(data => JSON.parse(data)), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.map)(({ checkpoint, documents }) => ({ checkpoint, documents: prepareIncomingWorkSessions(documents) })), (0,_tomoverse_utils_pipes_exponential_backoff_pipe__WEBPACK_IMPORTED_MODULE_9__.retryWithBackoff)(), (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)('RESYNC'))) }, push: { handler: createWorkSessionPushHandler(collection, http, syncUrl) }, replicationIdentifier: `work-session-replication-${syncUrl}`, // Waiting would stall the first sync after sign-out recreates the database. waitForLeadership: false }); return replicationState; }); return _setupWorkSessionCollection.apply(this, arguments); } function base64ToBlob(base64) { const binary = atob(base64); const bytes = new Uint8Array(binary.length); for (let index = 0; index < binary.length; index++) { // eslint-disable-next-line unicorn/prefer-code-point bytes[index] = binary.charCodeAt(index); } return (0,_rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_10__.toRxdbAttachmentBinary)(bytes); } /***/ }, /***/ 89967 /*!*******************************************************!*\ !*** ./libs/data-access/src/lib/guards/auth.guard.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ authGuard: () => (/* binding */ authGuard) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _services_auth_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../services/auth.service */ 52807); const PUBLIC_ROUTES = ['/login', '/sign-up']; const isPublicRoute = url => PUBLIC_ROUTES.some(route => url.startsWith(route)); const authGuard = (route, state) => { const authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_services_auth_service__WEBPACK_IMPORTED_MODULE_2__.AuthService); const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_1__.Router); const publicRoute = isPublicRoute(state.url); const isAuthenticated = authService.isAuthenticated(); if (isAuthenticated && publicRoute) { return router.createUrlTree(['/']); } if (!isAuthenticated && !publicRoute) { return router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } }); } return true; }; /***/ }, /***/ 5138 /*!******************************************************************!*\ !*** ./libs/data-access/src/lib/guards/session-cleanup.guard.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sessionCleanupGuard: () => (/* binding */ sessionCleanupGuard) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _services_auth_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../services/auth.service */ 52807); const sessionCleanupGuard = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_auth_service__WEBPACK_IMPORTED_MODULE_2__.AuthService); try { authService.currentUser.set(undefined); localStorage.clear(); } catch (error) { console.warn('Session cleanup skipped or failed:', error); } return true; }); return function sessionCleanupGuard() { return _ref.apply(this, arguments); }; }(); /***/ }, /***/ 94669 /*!************************************************************!*\ !*** ./libs/data-access/src/lib/rxdb-attachment-binary.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ toRxdbAttachmentBinary: () => (/* binding */ toRxdbAttachmentBinary) /* harmony export */ }); /* harmony import */ var _tomoverse_electron_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/electron-utils */ 63940); /** * Electron's context bridge serializes Blobs as empty objects. RxDB supports * Uint8Array attachment data in Electron, but reads Blob.size before IPC. */ const toRxdbAttachmentBinary = (data, type = 'application/octet-stream', isElectronEnvironment = (0,_tomoverse_electron_utils__WEBPACK_IMPORTED_MODULE_0__.isElectron)()) => { const bytes = Uint8Array.from(data instanceof Uint8Array ? data : new Uint8Array(data)); if (!isElectronEnvironment) return new Blob([bytes], { type }); const electronBytes = bytes; Object.defineProperty(electronBytes, 'size', { value: electronBytes.byteLength }); return electronBytes; }; /***/ }, /***/ 44769 /*!***************************************************************!*\ !*** ./libs/data-access/src/lib/services/app-init.service.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AppInitService: () => (/* binding */ AppInitService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 13329); /* harmony import */ var _db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../db/rxdb-manager.service */ 67189); /* harmony import */ var _auth_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./auth.service */ 52807); /* harmony import */ var _preferences_preferences_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./preferences/preferences.service */ 4508); class AppInitService { authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_auth_service__WEBPACK_IMPORTED_MODULE_7__.AuthService); rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_6__.RxdbManager); preferences = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_preferences_preferences_service__WEBPACK_IMPORTED_MODULE_8__.PreferencesService); init() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.firstValueFrom)(_this.authService.fetchUser().pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.take)(1), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.of)(undefined)))); if (!_this.authService.isAuthenticated()) { yield _this.authService.logout(); yield _this.rxdbManager.remove(); _this.preferences.clear(); return void 0; } yield _this.rxdbManager.init(); return void 0; })(); } static ɵfac = function AppInitService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AppInitService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: AppInitService, factory: AppInitService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 98765 /*!***********************************************************************!*\ !*** ./libs/data-access/src/lib/services/auth-interceptor.service.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AuthInterceptor: () => (/* binding */ AuthInterceptor) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 84356); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 162); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 88412); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 27588); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _cornerstonejs_core_utilities_logger__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @cornerstonejs/core/utilities/logger */ 67821); /* harmony import */ var _tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils/injection-tokens/env-injection-token */ 42035); /* harmony import */ var ___WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../.. */ 42541); class AuthInterceptor { logger = (0,_cornerstonejs_core_utilities_logger__WEBPACK_IMPORTED_MODULE_7__.getLogger)(AuthInterceptor.name); authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(___WEBPACK_IMPORTED_MODULE_9__.AuthService); env = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__.ENV); staticHosts = this.env.staticHosts; refreshRequest$; intercept(request, next) { const isStaticHost = this.staticHosts.some(host => request.url.includes(host)); if (isStaticHost) { return next.handle(request); } const accessToken = this.authService.getAccessToken(); const outgoing = accessToken ? request.clone(this.createAuthHeader(accessToken)) : request; return next.handle(outgoing).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_3__.catchError)(error => { const isRefreshRequest = request.url.includes('/oauth/refresh-token'); if (error.status === 401 && !isRefreshRequest) { return this.handle401Error(outgoing, next); } return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.throwError)(() => error); })); } handle401Error(request, next) { if (!this.refreshRequest$) { this.refreshRequest$ = this.authService.refreshTokens().pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_3__.catchError)(error => { this.logger.warn('Token refresh failed, logging out...'); return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(this.authService.logout()).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_3__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.throwError)(() => error)), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.switchMap)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.throwError)(() => error))); }), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.finalize)(() => { this.refreshRequest$ = undefined; }), (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.shareReplay)({ bufferSize: 1, refCount: false })); } return this.refreshRequest$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.switchMap)(({ accessToken }) => next.handle(request.clone(this.createAuthHeader(accessToken))))); } createAuthHeader(token) { return { setHeaders: { Authorization: `Bearer ${token}` } }; } static ɵfac = function AuthInterceptor_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AuthInterceptor)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AuthInterceptor, factory: AuthInterceptor.ɵfac }); } /***/ }, /***/ 52807 /*!***********************************************************!*\ !*** ./libs/data-access/src/lib/services/auth.service.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AuthService: () => (/* binding */ AuthService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 45541); /* harmony import */ var _cornerstonejs_core_utilities_logger__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @cornerstonejs/core/utilities/logger */ 67821); /* harmony import */ var _tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils/injection-tokens/env-injection-token */ 42035); /* harmony import */ var _preferences_preferences_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./preferences/preferences.service */ 4508); class AuthService { environment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__.ENV); http = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_4__.Router); preferences = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_preferences_preferences_service__WEBPACK_IMPORTED_MODULE_9__.PreferencesService); apiUrl = this.environment.apiUrl; accessTokenKey = 'accessToken'; refreshTokenKey = 'refreshToken'; logger = (0,_cornerstonejs_core_utilities_logger__WEBPACK_IMPORTED_MODULE_7__.getLogger)(AuthService.name); currentUser = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "currentUser" }] : [])); isAuthenticated = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => !!this.currentUser(), ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : [])); login(email, password) { this.logger.debug('Logging in...'); return this.http.post(`${this.apiUrl}/oauth/login`, { email, password }).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(response => !!response.accessToken && !!response.refreshToken), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.tap)(response => this.setOauthTokens(response.accessToken, response.refreshToken))); } signUp(firstName, lastName, email, password) { return this.http.post(`${this.apiUrl}/oauth/register`, { email, lastName, name: firstName, password }).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.tap)(response => { if (response.accessToken && response.refreshToken) { this.setOauthTokens(response.accessToken, response.refreshToken); } })); } fetchUser() { return this.http.get(`${this.apiUrl}/user/profile`).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.tap)(user => this.currentUser.set(user))); } logout() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this.logger.debug('Logging out...'); _this.currentUser.set(undefined); _this.router.navigate(['/login']); localStorage.removeItem(_this.accessTokenKey); localStorage.removeItem(_this.refreshTokenKey); // Session-scoped preferences (last store, filters, sort, ...) must not carry over // into the next login — clear them here rather than relying on next-boot detection, // since logging back in rarely triggers a full page reload. _this.preferences.clear(); })(); } loginWith(provider) { globalThis.location.href = `${this.apiUrl}/oauth/${provider}`; } setOauthTokens(accessToken, refreshToken) { localStorage.setItem(this.accessTokenKey, accessToken); localStorage.setItem(this.refreshTokenKey, refreshToken); } getAccessToken() { return localStorage.getItem(this.accessTokenKey) ?? undefined; } getRefreshToken() { return localStorage.getItem(this.refreshTokenKey) ?? undefined; } refreshTokens() { this.logger.debug('Refreshing auth token...'); return this.http.post(`${this.apiUrl}/oauth/refresh-token`, { refreshToken: this.getRefreshToken() }).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.tap)(response => this.setOauthTokens(response.accessToken, response.refreshToken))); } static ɵfac = function AuthService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AuthService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: AuthService, factory: AuthService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 40911 /*!******************************************************************!*\ !*** ./libs/data-access/src/lib/services/dev-options.service.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DevelopmentOptionsService: () => (/* binding */ DevelopmentOptionsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); const DEFAULTS = { clearDicomCacheOnStartup: true }; const STORAGE_KEY = 'tvct.devOptions'; class DevelopmentOptionsService { _options = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(this.load(), ...(ngDevMode ? [{ debugName: "_options" }] : [])); clearDicomCacheOnStartup = () => this._options().clearDicomCacheOnStartup; set(key, value) { this._options.update(options => { const updated = { ...options, [key]: value }; try { localStorage.setItem(STORAGE_KEY, JSON.stringify(updated)); } catch { // ignore storage errors } return updated; }); } load() { try { const stored = localStorage.getItem(STORAGE_KEY); if (stored) return { ...DEFAULTS, ...JSON.parse(stored) }; } catch { // ignore parse errors } return { ...DEFAULTS }; } static ɵfac = function DevelopmentOptionsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DevelopmentOptionsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: DevelopmentOptionsService, factory: DevelopmentOptionsService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 96269 /*!**********************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/dicom-api.service.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomApiService: () => (/* binding */ DicomApiService), /* harmony export */ batchFilesForUpload: () => (/* binding */ batchFilesForUpload) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/types */ 25575); /* harmony import */ var _tomoverse_utils_dicom_extract_dicom10__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/utils/dicom/extract-dicom10 */ 67227); /* harmony import */ var _tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils/injection-tokens/env-injection-token */ 42035); /* harmony import */ var _dicom_store_list_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./dicom-store-list.service */ 55643); const MAX_UPLOAD_BATCH_FILES = 100; /** * Groups files into batches that respect both a max file count and a max * cumulative byte size, so a batch never balloons past what the upload * endpoint's proxy will accept regardless of how large individual instances * are (a single-phase series has variable per-instance size, so capping only * file count still let a batch's total bytes run away). A single file that * alone exceeds maxBytes is still sent alone - splitting one DICOM instance's * bytes would produce an invalid file. */ function batchFilesForUpload(files, maxBytes = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__.MAX_UPLOAD_BATCH_BYTES, maxFiles = MAX_UPLOAD_BATCH_FILES) { if (!Number.isInteger(maxFiles) || maxFiles <= 0) { throw new Error(`batchFilesForUpload: maxFiles must be a positive integer, got ${maxFiles}`); } const batches = []; let currentBatch = []; let currentBytes = 0; for (const file of files) { const wouldExceedBytes = currentBatch.length > 0 && currentBytes + file.byteLength > maxBytes; const wouldExceedCount = currentBatch.length >= maxFiles; if (wouldExceedBytes || wouldExceedCount) { batches.push(currentBatch); currentBatch = []; currentBytes = 0; } currentBatch.push(file); currentBytes += file.byteLength; } if (currentBatch.length > 0) batches.push(currentBatch); return batches; } class DicomApiService { http = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient); environment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_8__.ENV); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_dicom_store_list_service__WEBPACK_IMPORTED_MODULE_9__.DicomStoreListService); /** Store-scoped WADO-RS/QIDO-RS proxy base. */ dicomWebUrl(storeUid) { return `${this.environment.apiUrl}/dicom/stores/${storeUid}/dicomweb`; } resolveVendor(storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const stores = yield _this.storeList.getEnabledStores(); return stores.find(store => store.uid === storeUid)?.vendor ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomVendor.ORTHANC; })(); } /** Omitting `limit` returns every study in the store. */ getStudies(storeUid, limit, offset) { let parameters = new _angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpParams().set('storeUids', storeUid); if (limit !== undefined) parameters = parameters.set('limit', limit); if (offset !== undefined) parameters = parameters.set('offset', offset); return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(this.http.get(`${this.environment.apiUrl}/dicom/studies`, { params: parameters })); } getSeriesForStudy(studyUid, storeUid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const parameters = new _angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpParams().set('storeUids', storeUid); const { rows } = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this2.http.get(`${_this2.environment.apiUrl}/dicom/studies/${studyUid}/series`, { params: parameters })); return rows.map(row => ({ institutionName: row.institutionName, modality: row.modality, patientID: row.patientID, patientName: row.patientName, seriesDate: row.seriesDate, seriesDescription: row.seriesDescription, seriesInstanceUID: row.seriesInstanceUID, seriesNumber: row.seriesNumber, seriesTime: row.seriesTime, studyDate: row.studyDate, studyDescription: row.studyDescription, studyInstanceUID: row.studyInstanceUID || studyUid })); })(); } getInstancesForSeries(studyUid, seriesUid, storeUid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const dicomInstances = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this3.http.get(`${_this3.dicomWebUrl(storeUid)}/studies/${studyUid}/series/${seriesUid}/metadata`)); const instances = (dicomInstances ?? []).map(instance => { return { instanceNumber: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.InstanceNumber), modality: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.Modality), patientID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.PatientID), patientName: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.PatientName)?.Alphabetic, rawMetadata: instance, seriesDescription: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.SeriesDescription), seriesInstanceUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.SeriesInstanceUID), seriesNumber: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.SeriesNumber), sopInstanceUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.SOPInstanceUID), studyDescription: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.StudyDescription), studyInstanceUID: (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_6__.getTagValue)(instance, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomTagId.StudyInstanceUID) }; }); instances.sort((a, b) => (a.instanceNumber ?? 0) - (b.instanceNumber ?? 0)); return instances; })(); } getInstanceImage(studyUid, seriesUid, instanceUid, storeUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const arrayBuffer = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this4.http.get(`${_this4.dicomWebUrl(storeUid)}/studies/${studyUid}/series/${seriesUid}/instances/${instanceUid}/rendered`, { headers: { Accept: 'image/jpeg' }, responseType: 'arraybuffer' })); const blob = new Blob([arrayBuffer], { type: 'image/jpeg' }); return blob; })(); } getInstanceDicomFile(studyUid, seriesUid, instanceUid, storeUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const isGoogleHealthcare = (yield _this5.resolveVendor(storeUid)) === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.DicomVendor.GOOGLE_HEALTHCARE; const acceptHeaders = isGoogleHealthcare ? [`application/dicom; transfer-syntax=${_this5.environment.transferSyntaxUid}`] : ['application/dicom', 'multipart/related; type=application/dicom']; let lastError; for (const acceptHeader of acceptHeaders) { try { const response = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this5.http.get(`${_this5.dicomWebUrl(storeUid)}/studies/${studyUid}/series/${seriesUid}/instances/${instanceUid}`, { headers: { Accept: acceptHeader }, observe: 'response', responseType: 'arraybuffer' })); const arrayBuffer = response.body; if (!arrayBuffer) { throw new Error('Empty DICOM instance response body'); } const bytes = new Uint8Array(arrayBuffer); const contentType = response.headers.get('content-type'); const isMultipart = _this5.isMultipartResponse(contentType, bytes); if (!isMultipart) { return arrayBuffer; } const dicomBytes = (0,_tomoverse_utils_dicom_extract_dicom10__WEBPACK_IMPORTED_MODULE_7__.extractDicomPart10)(bytes, { contentType }); return dicomBytes.buffer.slice(dicomBytes.byteOffset, dicomBytes.byteOffset + dicomBytes.byteLength); } catch (error) { lastError = error; } } if (lastError instanceof Error) { throw lastError; } throw new Error('Failed to retrieve DICOM instance'); })(); } uploadToStore(files, storeUid) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { let offset = 0; for (const batch of batchFilesForUpload(files)) { const form = new FormData(); for (const [index, file] of batch.entries()) { form.append('files', new Blob([file], { type: 'application/dicom' }), `instance-${offset + index}.dcm`); } yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this6.http.post(`${_this6.environment.apiUrl}/dicom/stores/${storeUid}/upload`, form)); offset += batch.length; } })(); } isMultipartResponse(contentType, bytes) { if (contentType) { const normalizedContentType = contentType.toLowerCase(); if (normalizedContentType.includes('multipart/related')) { return true; } if (normalizedContentType.includes('application/dicom')) { return false; } } const headerCheck = bytes.slice(0, Math.min(512, bytes.length)); const headerText = new TextDecoder('ascii', { fatal: false }).decode(headerCheck); if (/^(HTTP\/|Content-Type:|Content-Length:)/i.test(headerText)) { return true; } const dicmMagic = [0x44, 0x49, 0x43, 0x4d]; if (this.hasMagicAt(bytes, dicmMagic, 128) || this.hasMagicAt(bytes, dicmMagic, 0)) { return false; } return true; } hasMagicAt(bytes, magic, position) { if (bytes.length < position + magic.length) { return false; } return magic.every((byte, index) => bytes[position + index] === byte); } static ɵfac = function DicomApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomApiService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: DicomApiService, factory: DicomApiService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 67430 /*!*************************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/dicom-import.service.ts ***! \*************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomImportService: () => (/* binding */ DicomImportService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../db/rxdb-manager.service */ 67189); /* harmony import */ var _rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../rxdb-attachment-binary */ 94669); /* harmony import */ var _dicom_store_list_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./dicom-store-list.service */ 55643); const PARALLEL_FILE_IMPORTS = 4; class DicomImportService { rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_6__.RxdbManager); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_dicom_store_list_service__WEBPACK_IMPORTED_MODULE_8__.DicomStoreListService); uploadProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : [])); parseProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "parseProgress" }] : [])); totalProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => Math.round((this.uploadProgress() + this.parseProgress()) / 2), ...(ngDevMode ? [{ debugName: "totalProgress" }] : [])); isImporting = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "isImporting" }] : [])); fileProgress = []; totalBytes = 0; worker = new Worker(__webpack_require__.tu(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("libs_data-access_src_lib_services_dicom_worker_dicom-parse_worker_ts"), __webpack_require__.b)), { type: undefined }); pendingRequests = new Map(); constructor() { // eslint-disable-next-line unicorn/prefer-add-event-listener this.worker.onmessage = ({ data }) => { const pending = this.pendingRequests.get(data.id); if (!pending) return; this.pendingRequests.delete(data.id); if (data.ok) { pending.resolve(data.payload); return; } pending.reject(new Error(data.error)); }; } onFilesSelected(fileList, storeUid) { const files = Array.prototype.slice.call(fileList); if (files.length === 0) { console.warn('No files selected'); return; } const orderedFiles = this.interleaveByDirectory(files); this.isImporting.set(true); this.uploadProgress.set(0); this.parseProgress.set(0); this.fileProgress = Array.from({ length: orderedFiles.length }, () => 0); this.totalBytes = orderedFiles.reduce((total, file) => total + file.size, 0); this.processFiles(orderedFiles, storeUid).catch(error => { console.error('DICOM import failed', error); }); } /** * Reorders files round-robin across their parent directories. Exported DICOM * folders keep one series per directory, so this makes every imported series * show up in the staging table early instead of after the previous series. */ interleaveByDirectory(files) { const groups = new Map(); for (const file of files) { const path = file.webkitRelativePath || file.name; const directory = path.slice(0, path.lastIndexOf('/') + 1); const group = groups.get(directory); if (group) { group.push(file); } else { groups.set(directory, [file]); } } if (groups.size <= 1) return files; const buckets = [...groups.values()]; const interleaved = []; let round = 0; while (interleaved.length < files.length) { for (const bucket of buckets) { const file = bucket[round]; if (file) interleaved.push(file); } round += 1; } return interleaved; } processFiles(files, storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const targetStoreUid = storeUid ?? (yield _this.storeList.resolveStoreUid()); let parsedCount = 0; let nextIndex = 0; const importFromQueue = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { while (nextIndex < files.length) { const index = nextIndex++; const file = files[index]; if (!file) continue; try { const { buffer } = yield _this.readFileBuffer(file, index); _this.updateProgress(index, file.size); yield _this.arrayBufferToDicomWebJson(buffer, file, targetStoreUid); } catch (error) { // A file that became unreadable after selection must not abort the // remaining queue or leave the progress stuck below 100. console.error(`Failed to import ${file.name}`, error); _this.updateProgress(index, file.size); } parsedCount += 1; _this.parseProgress.set(Math.round(parsedCount / files.length * 100)); } }); return function importFromQueue() { return _ref.apply(this, arguments); }; }(); yield Promise.all(Array.from({ length: Math.min(PARALLEL_FILE_IMPORTS, files.length) }, importFromQueue)); } finally { _this.isImporting.set(false); } })(); } readFileBuffer(file, index) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const stream = file.stream?.(); if (!stream) { const buffer = yield file.arrayBuffer(); _this2.updateProgress(index, file.size); return { buffer, file, relativePath: file.webkitRelativePath || file.name }; } const reader = stream.getReader(); const chunks = []; let loaded = 0; while (true) { const { done, value } = yield reader.read(); if (done) break; if (value) { chunks.push(value); loaded += value.byteLength; _this2.updateProgress(index, Math.min(loaded, file.size)); } } const totalLength = chunks.reduce((total, chunk) => total + chunk.byteLength, 0); const combined = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { combined.set(chunk, offset); offset += chunk.byteLength; } return { buffer: combined.buffer, file, relativePath: file.webkitRelativePath || file.name }; })(); } updateProgress(index, loaded) { this.fileProgress[index] = loaded; const uploadedBytes = this.fileProgress.reduce((total, currentFileBytes) => total + currentFileBytes, 0); this.uploadProgress.set(this.totalBytes > 0 ? Math.round(uploadedBytes / this.totalBytes * 100) : 0); } arrayBufferToDicomWebJson(buffer, file, storeUid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const { metadata, naturalDataset } = yield _this3.parseInWorker(buffer); const seriesUid = naturalDataset.SeriesInstanceUID; const sopUid = naturalDataset.SOPInstanceUID; const studyUid = naturalDataset.StudyInstanceUID; if (!seriesUid || !sopUid || !studyUid) { return; } const seriesCollection = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this3.rxdbManager.dicomSeries$); const dicomSeries = { createdAt: Date.now(), id: (0,_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__.dicomSeriesId)(storeUid, seriesUid), institutionName: naturalDataset.InstitutionName, modality: naturalDataset.Modality ?? undefined, patientID: naturalDataset.PatientID ?? undefined, patientName: naturalDataset.PatientName?.[0]?.Alphabetic ?? undefined, seriesDate: naturalDataset.SeriesDate ?? naturalDataset['00080021'], seriesDescription: naturalDataset.SeriesDescription, seriesInstanceUID: seriesUid, seriesNumber: naturalDataset.SeriesNumber, storeUid, studyDate: naturalDataset.StudyDate ?? naturalDataset['00080020'], studyDescription: naturalDataset.StudyDescription, studyInstanceUID: studyUid }; yield seriesCollection.insertIfNotExists(dicomSeries); const instancesCollection = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this3.rxdbManager.dicomInstances$); const instance = { createdAt: Date.now(), id: (0,_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__.dicomInstanceId)(storeUid, sopUid), instanceNumber: naturalDataset.InstanceNumber, metadata, seriesUid, sopInstanceUID: sopUid, storeUid, studyUid, syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.RxDBSyncStatus.LOCAL }; let dicomDocument = yield instancesCollection.insertIfNotExists(instance); if (dicomDocument.syncStatus !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.RxDBSyncStatus.LOCAL) { dicomDocument = yield dicomDocument.incrementalPatch({ syncStatus: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.RxDBSyncStatus.LOCAL }); } const fileBuffer = yield file.arrayBuffer(); yield dicomDocument.putAttachment({ data: (0,_rxdb_attachment_binary__WEBPACK_IMPORTED_MODULE_7__.toRxdbAttachmentBinary)(fileBuffer), id: 'pixelData', type: 'application/dicom' }); } catch (error) { console.error('DICOM parse error', error); return; } })(); } parseInWorker(buffer) { return new Promise((resolve, reject) => { const id = crypto.randomUUID(); this.pendingRequests.set(id, { reject, resolve }); this.worker.postMessage({ buffer, id }, [buffer]); }); } static ɵfac = function DicomImportService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomImportService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: DicomImportService, factory: DicomImportService.ɵfac }); } /***/ }, /***/ 55643 /*!*****************************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/dicom-store-list.service.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomStoreListService: () => (/* binding */ DicomStoreListService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils/injection-tokens/env-injection-token */ 42035); /* harmony import */ var _preferences_preferences_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../preferences/preferences.service */ 4508); class DicomStoreListService { http = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient); environment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_4__.ENV); preferences = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_preferences_preferences_service__WEBPACK_IMPORTED_MODULE_5__.PreferencesService); enabledStores; /** Enabled stores only, sorted by `name`. Cached across the session. */ getEnabledStores() { this.enabledStores ??= this.fetchEnabledStores().catch(error => { this.enabledStores = undefined; throw error; }); return this.enabledStores; } /** * The persisted store if it is still enabled, otherwise the first enabled store. */ resolveStoreUid() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const stores = yield _this.getEnabledStores(); const persisted = _this.preferences.get().storeUid; if (persisted && stores.some(store => store.uid === persisted)) return persisted; const first = stores[0]; if (!first) throw new Error('No enabled DICOM store available.'); return first.uid; })(); } /** * Enabled stores that also respond to a ping — safe to show in store-selection UI. * Not cached: reachability can change between opens. */ getReachableStores() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const enabled = yield _this2.getEnabledStores(); const results = yield Promise.allSettled(enabled.map(store => (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this2.http.get(`${_this2.environment.apiUrl}/dicom/stores/${store.uid}/ping`)))); return enabled.filter((_, index) => { const result = results[index]; return result?.status === 'fulfilled' && result.value.reachable; }); })(); } /** * Store-wide statistics for one store. Not cached: contents change with imports. */ getStoreStatistics(storeUid) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(this.http.get(`${this.environment.apiUrl}/dicom/stores/${storeUid}/stats`)); } fetchEnabledStores() { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const stores = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this3.http.get(`${_this3.environment.apiUrl}/v1/dicom-store`)); return stores.filter(store => store.enabled).map(({ enabled, name, uid, url, vendor }) => ({ enabled, name, uid, url, vendor })).toSorted((a, b) => a.name.localeCompare(b.name)); })(); } static ɵfac = function DicomStoreListService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomStoreListService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: DicomStoreListService, factory: DicomStoreListService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 68453 /*!*****************************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/rendering-engine.service.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RenderingEngineService: () => (/* binding */ RenderingEngineService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 70611); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 50600); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @cornerstonejs/core */ 77569); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @cornerstonejs/core/enums */ 15247); /* harmony import */ var _kitware_vtk_js_Common_DataModel_DataSet_Constants__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/DataSet/Constants */ 78865); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_post_process__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/post-process */ 16352); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const DEFAULT_HIT_RADIUS = 5; class RenderingEngineService { cornerstoneInit = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.CornerstoneInitService); cornerstoneRenderingEngine; viewportsReady = false; volumeLoaded = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "volumeLoaded" }] : [])); /** One pipeline per offscreen render window. Cornerstone shares * render windows across viewports, so the key is the window. */ pipelines = new Map(); setViewportsReady() { this.viewportsReady = true; } constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => { this.destroy(); }); } init() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this.viewportsReady = false; _this.destroy(); yield _this.cornerstoneInit.ensureInitialized(); })(); } ENGINE_ID = 'tomoverse-rendering-engine'; enable(element, options) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this2.cornerstoneRenderingEngine = _this2.cornerstoneRenderingEngine ?? (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__.getRenderingEngine)(_this2.ENGINE_ID) ?? new _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__["default"](_this2.ENGINE_ID); const { id: viewportId, volumeId } = options; const viewportInput = { defaultOptions: { background: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.cssVariableToNormalizedRgb)('--p-app-viewport-background'), suppressEvents: true // Prevent cornerstone from handling keyboard/mouse events }, element, type: options?.type ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportType.ORTHOGRAPHIC, viewportId }; const existing = _this2.getViewport(viewportId); if (existing?.element === element) return; _this2.cornerstoneRenderingEngine.enableElement(viewportInput); const viewport = _this2.getViewport(viewportId); if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.isBaseVolumeViewportLike)(viewport)) { _this2.configureHardwareSelector(viewport); yield viewport.setVolumes([{ volumeId }]); // The 3D viewport hosts vascular/endo rendering and scalar masking, // which needs vtk.js's stock multi-input volume mapper. // Cornerstone installs its streaming mapper by default, so swap it here. if (options?.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportType.VOLUME_3D) { for (const { actor } of viewport.getActors()) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.swapToStandardVolumeMapper)(actor); } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.installTransparentSampleEarlyOut)(viewport); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyVolume3dSampleDistance)(viewport); } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.initAnnotationOverlay)(viewport); } _this2.installPostProcessPipelineFor(viewportId); })(); } /** Append a `PostProcessPipeline` after vtk.js's `vtkForwardPass`, * with the outline pass installed. */ installPostProcessPipelineFor(viewportId) { const renderWindow = this.getRenderWindow(viewportId); if (!renderWindow) return; if (this.pipelines.has(renderWindow)) return; const pipeline = _tomoverse_post_process__WEBPACK_IMPORTED_MODULE_9__.vtkPostProcessPipeline.newInstance(); pipeline.addPass(new _tomoverse_post_process__WEBPACK_IMPORTED_MODULE_9__.OutlineEffectPass()); if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.getDebugFlagByName)('postProcess')) { pipeline.addPass(new _tomoverse_post_process__WEBPACK_IMPORTED_MODULE_9__.MaskPreviewPass()); } renderWindow.setRenderPasses([...renderWindow.getRenderPasses(), pipeline]); this.pipelines.set(renderWindow, pipeline); } /** Returns every installed pass with the given id across all active pipelines. */ getPostProcessPassesById(id) { const passes = []; for (const pipeline of this.pipelines.values()) { const pass = pipeline.getPass(id); if (pass) passes.push(pass); } return passes; } renderAll() { this.cornerstoneRenderingEngine?.render(); } renderViewports(viewportIds) { if (viewportIds.length === 0) return; this.cornerstoneRenderingEngine?.renderViewports(viewportIds); } disable(viewportId) { this.cornerstoneRenderingEngine?.disableElement(viewportId); } updateMPRWindow(windowWidth, windowLevel, render = true) { if (!this.cornerstoneRenderingEngine) return; const mprViewports = this.cornerstoneRenderingEngine.getViewports().filter(viewport => { return viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportType.PERSPECTIVE || viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportType.ORTHOGRAPHIC; }); for (const viewport of mprViewports) { if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.isBaseVolumeViewportLike)(viewport)) break; this.applyVOI(viewport, windowWidth, windowLevel); } if (render) this.renderAll(); } updateVolume3dViewportWindow({ brightness, lighting, presetName, render, threshold, thresholds, volume3dViewport, widths }) { if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.isBaseVolumeViewportLike)(volume3dViewport)) return; switch (presetName) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.ENDO: { this.applyEndoPreset(volume3dViewport, presetName, thresholds, render, lighting, widths); return; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.FLUOROSCOPIC: { this.applyFluoroscopicPreset(volume3dViewport, presetName, false, threshold, brightness); return; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.MIP: { this.applyMipPreset(volume3dViewport, presetName, threshold, brightness, render); return; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.VASCULAR: { if (thresholds !== undefined) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyVascularPresetToViewport)(volume3dViewport, thresholds.tissueBloodThreshold, thresholds.bloodCalciumThreshold, thresholds.outlierOpacity ?? 0, render, lighting, widths?.opacityTransitionWidth); } return; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.XRAY: { this.applyFluoroscopicPreset(volume3dViewport, presetName, true, threshold, brightness); return; } } if (render) volume3dViewport.render(); } applyEndoPreset(viewport, presetName, thresholds, render, lighting, widths) { if (thresholds?.airTissueThreshold === undefined) { this.applyPreset(viewport.id, presetName, render); return; } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyEndoPresetToViewport)(viewport, thresholds.airTissueThreshold, thresholds.tissueBloodThreshold, thresholds.bloodCalciumThreshold, render, lighting, widths?.opacityTransitionWidth, widths?.rgbTransitionWidth); } destroy() { if (this.cornerstoneRenderingEngine) { // Cornerstone calls registered widgets back mid-destroy, after the context pool // they need is gone; a throw there strands the engine in its global cache. for (const viewport of this.cornerstoneRenderingEngine.getViewports()) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.detachAnnotationOverlay)(viewport); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.clearViewportWidgets)(viewport); } this.cornerstoneRenderingEngine.destroy(); this.cornerstoneRenderingEngine = undefined; } for (const pipeline of this.pipelines.values()) pipeline.delete(); this.pipelines.clear(); _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__["default"].purgeCache(); } getWorldPosition(viewportId, screenPos) { const viewport = this.getViewport(viewportId); if (!viewport) return; return viewport.canvasToWorld(screenPos); } /** Projects a world point to canvas coordinates. * Inverse of canvasToWorld on the click plane */ worldToCanvas(viewportId, worldPos) { return this.getViewport(viewportId)?.worldToCanvas(worldPos); } /** World-space pick ray. Branches on viewport type. */ getWorldRay(viewportId, screenPos) { const viewport = this.getViewport(viewportId); if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"]) return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.rayFromCamera)(viewport, screenPos); const mpr = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.getMprViewport)(viewport); return mpr ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.rayFromSlicePlane)(mpr, screenPos) : undefined; } /** Returns the t-parameter range for valid intersection points along an MPR slab ray. Returns undefined for 3D viewports. */ getSliceTRange(viewportId, zeroSlabEpsilon = 0.5) { const viewport = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.getMprViewport)(this.getViewport(viewportId)); if (!viewport) return undefined; const thickness = viewport.getSlabThickness?.() ?? 0; const half = thickness > 0 ? thickness / 2 : zeroSlabEpsilon; return [-half, half]; } /** Returns the right and up unit vectors that span the MPR slab plane. Returns undefined for 3D viewports. */ cameraSlabPlaneAxes(viewportId) { const viewport = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.getMprViewport)(this.getViewport(viewportId)); return viewport ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.slabAxesForViewport)(viewport) : undefined; } /** True when a viewport canvas's size no longer matches its CSS size * devicePixelRatio. * * DPR belongs to the display, not the window (OS scale change, move to a differently-scaled * monitor), so it can change without a usable `resize` event. */ hasStaleCanvasResolution() { const dpr = window.devicePixelRatio || 1; return this.getActiveViewports().some(({ canvas }) => { if (!canvas || canvas.clientWidth === 0 || canvas.clientHeight === 0) return false; return Math.abs(canvas.width - canvas.clientWidth * dpr) > 1 || Math.abs(canvas.height - canvas.clientHeight * dpr) > 1; }); } resetCameraForResize() { // `vtkOffscreenMultiRenderWindow.resize()` does an unguarded render // that bypasses cornerstone's per-pass widget toggling. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.silenceAnnotationOverlays)(); this.cornerstoneRenderingEngine?.resize(true, true); this.fixActorMappers(); // Cornerstone re-tiles its offscreen canvas on resize — each primary // renderer gets a new viewport rectangle, so overlays must follow. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.resyncAnnotationOverlayViewports)(this.getActiveViewports()); } fixActorMappers() { // When the rendering engine resizes, the existing vtkMapper instances // stop working and all actors disappear. // This appears to be because Cornerstone created a new WebGL context internally, // so we have to mark the mappers/actors as modified to refresh them. for (const viewport of this.getActiveViewports()) { const actors = [...viewport.getActors().map(entry => entry.actor), ...(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.getAnnotationActors)(viewport.id)]; for (const actor of actors) { const mapper = actor.getMapper(); if (mapper) { mapper.modified(); actor.modified(); } } } } /** hitRadius defaults to the standard pick tolerance - callers pass a larger value to * widen the search window for a specific target (see AnnotationCreateInteraction/ * HoverInteraction's closed-spline first-point checks). */ getScreenPositionActor(viewportId, screenPos, hitRadius = DEFAULT_HIT_RADIUS) { if (!this.viewportsReady) return undefined; const viewport = this.getViewport(viewportId); if (!viewport) return undefined; // Offset mousePos to the viewport's location on the offscreen canvas. // Also account for devicePixelRatio for different devices/zoom levels. const dpr = window.devicePixelRatio || 1; const [vtkX, vtkY] = [Math.floor(screenPos[0] * dpr + viewport.sx), Math.floor(viewport.sHeight - screenPos[1] * dpr + viewport.sy) // Flip y ]; const view = viewport.getRenderer().getRenderWindow().getInteractor().getView(); const selector = view.getSelector(); selector.setArea([vtkX - hitRadius, vtkY - hitRadius, vtkX + hitRadius, vtkY + hitRadius]); const overlayActor = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.pickFromOverlay)(viewportId, selector, view, vtkX, vtkY, hitRadius); if (overlayActor) return overlayActor; if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"]) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.pickFromVolume3DPrimary)(viewport, selector, view, vtkX, vtkY, hitRadius); } return undefined; } getActiveViewports() { return this.cornerstoneRenderingEngine?.getViewports() ?? []; } /** * Rebind each base-volume viewport to a different volume (a phase swap) without rendering, so the * caller can re-apply render settings before the first paint and avoid a flash of reset state. */ setActiveVolume(volumeIds) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const updates = _this3.getActiveViewports().filter(viewport => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.isBaseVolumeViewportLike)(viewport)).map(viewport => { const volumeId = viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"] ? volumeIds.volume3dId : volumeIds.mprVolumeId; return viewport.setVolumes([{ volumeId }], false); }); yield Promise.all(updates); // setVolumes recreates actors/mappers: the shared mapper comes back (GPU // vascular masking needs the stock one), shader replacements drop, and // sampling reverts to the half-voxel default — redo all three. for (const viewport of _this3.getActiveViewports()) { if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"]) { for (const { actor } of viewport.getActors()) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.swapToStandardVolumeMapper)(actor); } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.installTransparentSampleEarlyOut)(viewport); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyVolume3dSampleDistance)(viewport); } } })(); } getViewport(viewportId) { return this.cornerstoneRenderingEngine?.getViewport(viewportId); } getRenderWindow(viewportId) { const viewports = this.getActiveViewports(); if (!this.cornerstoneRenderingEngine || viewports.length === 0) return; const offscreenRenderWindow = this.cornerstoneRenderingEngine.getOffscreenMultiRenderWindow(viewportId ?? viewports[0]?.id); return offscreenRenderWindow.getOpenGLRenderWindow(); } waitForViewportIsReady(viewportId) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return new Promise(resolve => { const checkViewport = () => { const viewport = _this4.getViewportIfReady(viewportId); if (viewport) { resolve(viewport); } else { requestAnimationFrame(checkViewport); } }; checkViewport(); }); })(); } applyPreset(viewportId, selectedPreset, render = true) { const viewport = this.getViewport(viewportId); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"])) { console.warn('Not a VolumeViewport3D', viewportId); return; } viewport.setProperties({ preset: selectedPreset }); if (render) viewport.render(); } applyFluoroscopicPreset(viewport, presetName, isXray, threshold, brightness) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyFluoroscopicPresetToViewport)(viewport, presetName, isXray, threshold, brightness); } applyMipPreset(viewport, presetName, threshold, brightness, render) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.applyMipPresetToViewport)(viewport, presetName, threshold, brightness, render); } adjustClippingPlane(viewportId, proximalDistance, distalDistance) { if (proximalDistance <= distalDistance + 1) { return; } const viewport = this.getViewport(viewportId); if (!viewport || !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"])) { console.warn('Viewport not found for adjusting clipping planes', viewportId); return; } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.adjustProximalAndDistalClippingPlanes)(viewport, proximalDistance, distalDistance); viewport.render(); } configureHardwareSelector(viewport) { const selector = viewport.getRenderer().getRenderWindow().getInteractor().getView().getSelector(); selector.setCaptureZValues(true); selector.setFieldAssociation(_kitware_vtk_js_Common_DataModel_DataSet_Constants__WEBPACK_IMPORTED_MODULE_7__.FieldAssociations.FIELD_ASSOCIATION_CELLS); } applyVOI(viewport, width, level) { const lower = level - width / 2; const upper = level + width / 2; viewport.setProperties({ voiRange: { lower, upper } }); } isViewportReady(viewportId) { return !!this.getViewportIfReady(viewportId); } getViewportIfReady(viewportId) { const viewport = this.getViewport(viewportId); if (viewport?.viewportStatus !== _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_6__["default"].RENDERED) { return; } return viewport; } static ɵfac = function RenderingEngineService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RenderingEngineService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: RenderingEngineService, factory: RenderingEngineService.ɵfac }); } /***/ }, /***/ 75826 /*!**************************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/study-search.provider.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ClientStudySearchProvider: () => (/* binding */ ClientStudySearchProvider), /* harmony export */ StudySearchProvider: () => (/* binding */ StudySearchProvider) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 46046); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 84356); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 27588); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _dicom_api_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./dicom-api.service */ 96269); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/core */ 14975); class StudySearchProvider {} /** * Client-side adapter: fetches the whole store into memory once, then filters, sorts and slices each requested page from that cache * instantly. Aggregates are computed over the full filtered set. */ class ClientStudySearchProvider extends StudySearchProvider { api = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_dicom_api_service__WEBPACK_IMPORTED_MODULE_8__.DicomApiService); caches = new Map(); search(query) { return this.accumulate(query.storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_4__.map)(accumulated => toPage(accumulated, query))); } invalidate(storeUid) { if (storeUid) this.caches.delete(storeUid);else this.caches.clear(); } accumulate(storeUid) { let cached = this.caches.get(storeUid); if (!cached) { cached = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.defer)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.from)(this.fetchAll(storeUid))).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.shareReplay)(1)); this.caches.set(storeUid, cached); } return cached; } /** One request for the whole store, the backend returns every study when no limit is sent. */ fetchAll(storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { rows, total } = yield _this.api.getStudies(storeUid); return { rows, truncated: total !== undefined && rows.length < total }; })(); } static ɵfac = /*@__PURE__*/(() => { let ɵClientStudySearchProvider_BaseFactory; return function ClientStudySearchProvider_Factory(__ngFactoryType__) { return (ɵClientStudySearchProvider_BaseFactory || (ɵClientStudySearchProvider_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵgetInheritedFactory"](ClientStudySearchProvider)))(__ngFactoryType__ || ClientStudySearchProvider); }; })(); static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: ClientStudySearchProvider, factory: ClientStudySearchProvider.ɵfac }); } function withReviewStatus(rows, statuses) { return rows.map(row => { const reviewStatus = statuses?.get(row.studyInstanceUID) ?? 'none'; return { ...row, reviewStatus, reviewStatusRank: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_6__.reviewStatusRank)(reviewStatus) }; }); } function toPage(accumulated, query) { const rows = withReviewStatus(accumulated.rows, query.reviewStatuses); const filtered = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_7__.filterStudies)(rows, query.criteria); const sorted = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_7__.sortRows)(filtered, query.sort); const { limit, offset } = query.page; return { aggregates: { instanceSum: sumIfKnown(filtered, row => row.numberOfInstances), seriesSum: sumIfKnown(filtered, row => row.numberOfSeries) }, rows: sorted.slice(offset, offset + limit), total: filtered.length, truncated: accumulated.truncated }; } /** Sums a count over rows, or `undefined` when no row provides it (so the UI omits it, not shows 0). */ function sumIfKnown(rows, pick) { let sum; for (const row of rows) { const value = pick(row); if (value !== undefined) sum = (sum ?? 0) + value; } return sum; } /***/ }, /***/ 79950 /*!**************************************************************************!*\ !*** ./libs/data-access/src/lib/services/dicom/volume-loader.service.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeLoaderService: () => (/* binding */ VolumeLoaderService), /* harmony export */ parseImageId: () => (/* binding */ parseImageId), /* harmony export */ separateSeriesPhases: () => (/* binding */ separateSeriesPhases) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncIterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncIterator.js */ 75105); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(dicom_parser__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/types */ 25575); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); /* harmony import */ var _tomoverse_utils_cornerstone_cornerstone_core_token__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/utils/cornerstone/cornerstone-core.token */ 83283); /* harmony import */ var _tomoverse_utils_cornerstone_tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils/cornerstone/tomoverse-volume-scheme */ 3389); /* harmony import */ var _tomoverse_utils_dicom_dicom_image_loader_token__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/utils/dicom/dicom-image-loader.token */ 14007); /* harmony import */ var _tomoverse_utils_dicom_extract_window_metadata__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils/dicom/extract-window-metadata */ 1712); /* harmony import */ var _tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/utils/multiphase */ 71717); /* harmony import */ var _db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../db/dicom/dicom-database.service */ 30860); const IMAGE_SCHEME = 'tomoverse-dcm'; const IMAGE_ID_SEPARATOR = '|'; function buildImageId(storeUid, seriesUid, sopInstanceUID) { return `${IMAGE_SCHEME}:${[storeUid, seriesUid, sopInstanceUID].join(IMAGE_ID_SEPARATOR)}`; } function parseImageId(imageId) { const [storeUid, seriesUid, sopInstanceUID] = imageId.replace(`${IMAGE_SCHEME}:`, '').split(IMAGE_ID_SEPARATOR); if (!storeUid || !seriesUid || !sopInstanceUID) { throw new Error(`Invalid imageId: ${imageId}`); } return { seriesUid, sopInstanceUID, storeUid }; } // Pure (no cornerstone/prefetch) — reused by the pre-load modal. function buildVolumeSeriesPhases(entries) { const phaseInstances = entries.map(entry => ({ id: entry.imageId, metadata: entry.metadata, sortOrder: entry.sortOrder })); const metadataByImageId = new Map(entries.map(entry => [entry.imageId, entry.metadata])); const phases = (0,_tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__.separatePhases)(phaseInstances); if (phases.length > 1) { return { phases: phases.map(phase => ({ id: phase.id, identification: (0,_tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__.describePhase)(metadataByImageId.get(phase.memberIds[0] ?? '')), imageIds: phase.memberIds, label: phase.label, order: phase.order })), unseparable: false }; } const sortedEntries = entries.toSorted((a, b) => a.sortOrder - b.sortOrder); return { phases: [{ id: 'default:0', identification: (0,_tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__.describePhase)(sortedEntries[0]?.metadata), imageIds: sortedEntries.map(({ imageId }) => imageId), label: '1', order: 1 }], unseparable: (0,_tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__.looksMultiphase)(phaseInstances) }; } // Metadata-only (no prefetch); takes the root db so it runs before the viewer exists. function separateSeriesPhases(_x, _x2, _x3, _x4, _x5) { return _separateSeriesPhases.apply(this, arguments); } function _separateSeriesPhases() { _separateSeriesPhases = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (database, studyUid, seriesUid, storeUid, onInstance) { const entries = []; var _iteratorAbruptCompletion = false; var _didIteratorError = false; var _iteratorError; try { for (var _iterator = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncIterator_js__WEBPACK_IMPORTED_MODULE_1__["default"])(database.streamSeriesMetadata(studyUid, seriesUid, storeUid)), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) { const { instanceNumber, metadata, sopInstanceUID } = _step.value; { // imageId carries storeUid so the on-demand `loadImage` callback (which // only receives an imageId) fetches from the right store, and the // cornerstone metaDataManager is store-scoped. const imageId = buildImageId(storeUid, seriesUid, sopInstanceUID); onInstance?.(imageId, metadata); const metadataValue = metadata; const metadataInstanceNumber = (0,_tomoverse_utils_multiphase__WEBPACK_IMPORTED_MODULE_11__.toFiniteNumber)((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_5__.getTagValue)(metadataValue, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.DicomTagId.InstanceNumber)); entries.push({ imageId, metadata: metadataValue, sortOrder: (typeof instanceNumber === 'number' ? instanceNumber : undefined) ?? metadataInstanceNumber ?? entries.length }); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (_iteratorAbruptCompletion && _iterator.return != null) { yield _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return buildVolumeSeriesPhases(entries); }); return _separateSeriesPhases.apply(this, arguments); } function sopUidsForPhases(phases, selectedPhaseIds) { const selected = new Set(selectedPhaseIds); return phases.filter(phase => selected.has(phase.id)).flatMap(phase => phase.imageIds).map(imageId => parseImageId(imageId).sopInstanceUID); } class VolumeLoaderService { dicomImageLoader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_dicom_dicom_image_loader_token__WEBPACK_IMPORTED_MODULE_9__.DICOM_IMAGE_LOADER); cornerstoneCore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_cornerstone_cornerstone_core_token__WEBPACK_IMPORTED_MODULE_7__.CORNERSTONE_CORE); datasets = new Map(); loadingTasks = new Map(); phaseLoadingTasks = new Map(); unseparableSeries = new Map(); activePrefetchCount = 0; customLoaderRegistered = false; dicomDatabaseService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_db_dicom_dicom_database_service__WEBPACK_IMPORTED_MODULE_12__.DicomDatabaseService); isCachingSource = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(false, ...(ngDevMode ? [{ debugName: "isCachingSource" }] : [])); init() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this.dicomImageLoader.init({ decodeConfig: { wasmUrlCodecCharls: './charlswasm_decode.wasm', wasmUrlCodecLibJpegTurbo8bit: './libjpegturbowasm_decode.wasm', wasmUrlCodecOpenJpeg: './openjpegwasm_decode.wasm', wasmUrlCodecOpenJph: './openjphjs.wasm' }, // @ToDo: Remove once Cornerstone fixes the custom webworker path issue: https://github.com/cornerstonejs/cornerstone3D/pull/1982 webWorkerFactory: () => { return new Worker(__webpack_require__.tu(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("apps_viewer_src_cornerstone-image-decoder_worker_ts"), __webpack_require__.b))); } }); if (!_this.customLoaderRegistered) { _this.cornerstoneCore.volumeLoader.registerVolumeLoader(_tomoverse_utils_cornerstone_tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_8__.TOMOVERSE_IMAGE_VOLUME_SCHEME, (volumeId, options) => _this.cornerstoneCore.cornerstoneStreamingImageVolumeLoader(volumeId, options)); _this.cornerstoneCore.imageLoader.registerImageLoader(IMAGE_SCHEME, imageId => ({ promise: _this.loadImage(imageId) })); _this.cornerstoneCore.metaData.addProvider((type, imageId) => { if (!imageId.startsWith(`${IMAGE_SCHEME}:`)) return; try { const dataSet = _this.datasets.get(imageId); if (!dataSet) return; return _this.dicomImageLoader.wadouri.metaData.metadataForDataset(type, imageId, dataSet); } catch { return; } }, 1000); _this.customLoaderRegistered = true; } })(); } getWindowMetadata(imageIds) { const firstImage = imageIds[0]; if (firstImage) { const firstImageMetadata = this.dicomImageLoader.wadors.metaDataManager.get(firstImage); return (0,_tomoverse_utils_dicom_extract_window_metadata__WEBPACK_IMPORTED_MODULE_10__.extractWindowMetadata)(firstImageMetadata, { level: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_6__.DEFAULT_WINDOW_PRESET.level, width: _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_6__.DEFAULT_WINDOW_PRESET.width }); } throw new Error('No images found. Make sure that images are loaded first.'); } streamSeriesCacheProgress(seriesUid, storeUid) { return this.dicomDatabaseService.streamSeriesCacheProgress(seriesUid, storeUid); } ensureImageIds(studyUid, seriesUid, storeUid) { const cacheKey = `${storeUid}:${studyUid}:${seriesUid}`; const existing = this.loadingTasks.get(cacheKey); if (existing) return existing; const phasePromise = this.ensureSeriesPhases(studyUid, seriesUid, storeUid); return this.loadingTasks.get(cacheKey) ?? phasePromise.then(phases => phases.flatMap(phase => phase.imageIds)); } /** * Separate a series into its phases (multiphase) or a single phase (everything else), registering * each instance's metadata as it streams. Caches the result; flags the series unseparable when it * looks multiphase but cannot be split. `selectedPhaseIds` scopes the prefetch to those phases. */ ensureSeriesPhases(studyUid, seriesUid, storeUid, selectedPhaseIds) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const cacheKey = `${storeUid}:${studyUid}:${seriesUid}`; const existing = _this2.phaseLoadingTasks.get(cacheKey); if (existing) return existing; const loadPromise = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { phases, unseparable } = yield separateSeriesPhases(_this2.dicomDatabaseService, studyUid, seriesUid, storeUid, (imageId, metadata) => _this2.dicomImageLoader.wadors.metaDataManager.add(imageId, metadata)); _this2.unseparableSeries.set(cacheKey, unseparable); // Warm the binary cache for the selected phases (all when none specified); don't block on it. const sopInstanceUIDs = selectedPhaseIds && selectedPhaseIds.length > 0 ? sopUidsForPhases(phases, selectedPhaseIds) : undefined; _this2.markPrefetchStarted(); _this2.dicomDatabaseService.prefetchInstanceBinaries(studyUid, seriesUid, storeUid, sopInstanceUIDs).catch(error => console.error('Series prefetch failed', error)).finally(() => _this2.markPrefetchFinished()); return phases; })(); // Mirror the in-flight work into loadingTasks so concurrent ensureImageIds() callers share it // (as flat image ids); both keys are cleared together below. _this2.phaseLoadingTasks.set(cacheKey, loadPromise); _this2.loadingTasks.set(cacheKey, loadPromise.then(phases => phases.flatMap(phase => phase.imageIds))); return loadPromise.finally(() => { _this2.phaseLoadingTasks.delete(cacheKey); _this2.loadingTasks.delete(cacheKey); }); })(); } /** Whether the last separation of this series found it multiphase but could not split it. */ wasSeriesUnseparable(studyUid, seriesUid, storeUid) { return this.unseparableSeries.get(`${storeUid}:${studyUid}:${seriesUid}`) ?? false; } markPrefetchStarted() { this.activePrefetchCount += 1; this.isCachingSource.set(true); } markPrefetchFinished() { this.activePrefetchCount = Math.max(0, this.activePrefetchCount - 1); this.isCachingSource.set(this.activePrefetchCount > 0); } /** * If `seriesUid` is a TOMOVERSE OT annotation export, reads the source CT series UID * (tag 0099,1004) and the list of CT instance UIDs (tag 0099,1005) from the single OT * instance. Returns undefined for normal CT series. * * Tags are read directly from the DICOM binary rather than WADO-RS metadata because * WADO-RS LO values are limited to 64 chars per component — a long backslash-joined * UID list would be truncated and only the first UID would survive indexing. */ resolveSourceInfo(studyUid, seriesUid, storeUid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instances = yield _this3.dicomDatabaseService.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid); const first = instances[0]; if (!first) return undefined; // Use public Manufacturer tag — always indexed in WADO-RS (unlike private creator tags). const meta = first.toJSON().metadata; if (String(meta?.['00080070']?.Value?.[0] ?? '').trim() !== 'Tomoverse Imaging') return undefined; // Read tags directly from the binary to avoid WADO-RS UT truncation. const binary = yield _this3.dicomDatabaseService.getBinary(first.sopInstanceUID, storeUid); const sourceSeriesUid = _this3.readSequenceItemTag(binary, 0x00_08, 0x11_15, 0x00_20, 0x00_0e); if (!sourceSeriesUid) return undefined; const sourceInstanceUids = new Set(_this3.readSequenceItemTags(binary, 0x00_08, 0x21_12, 0x00_08, 0x11_55)); return { sourceInstanceUids, sourceSeriesUid }; })(); } /** Parse a DICOM binary, returning undefined on failure. */ parseBinary(buffer) { try { return dicom_parser__WEBPACK_IMPORTED_MODULE_3___default().parseDicom(new Uint8Array(buffer)); } catch { return undefined; } } /** Decode element bytes to a trimmed string. */ decodeElement(dataSet, element) { return new TextDecoder().decode(dataSet.byteArray.slice(element.dataOffset, element.dataOffset + element.length)).replaceAll('\0', '').trim(); } elementKey(group, element) { return `x${(group * 0x1_00_00 + element).toString(16).padStart(8, '0')}`; } /** Read the first item of a sequence tag and return the value of a child tag. */ readSequenceItemTag(buffer, sqGroup, sqElement, childGroup, childElement) { const dataSet = this.parseBinary(buffer); if (!dataSet) return undefined; const itemSet = dataSet.elements[this.elementKey(sqGroup, sqElement)]?.items?.[0]?.dataSet; if (!itemSet) return undefined; const element = itemSet.elements[this.elementKey(childGroup, childElement)]; return element ? this.decodeElement(itemSet, element) : undefined; } /** Read a child tag value from every item in a sequence tag. */ readSequenceItemTags(buffer, sqGroup, sqElement, childGroup, childElement) { const dataSet = this.parseBinary(buffer); if (!dataSet) return []; const uids = []; for (const item of dataSet.elements[this.elementKey(sqGroup, sqElement)]?.items ?? []) { const itemSet = item.dataSet; if (!itemSet) continue; const element = itemSet.elements[this.elementKey(childGroup, childElement)]; if (element) uids.push(this.decodeElement(itemSet, element)); } return uids; } loadImage(imageId) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { sopInstanceUID, storeUid } = parseImageId(imageId); // getBinary's own network fetch queues on DicomDatabaseService's shared, single global // concurrency limit - no separate limiter needed here (see that limiter's comment for why // having two independently-sized ones was actually letting more fetches run at once, not // fewer). const buffer = yield _this4.dicomDatabaseService.getBinary(sopInstanceUID, storeUid); const blob = new Blob([buffer], { type: 'application/dicom' }); const file = new File([blob], `${sopInstanceUID}.dcm`, { type: 'application/dicom' }); const fileImageId = _this4.dicomImageLoader.wadouri.fileManager.add(file); const image = yield _this4.cornerstoneCore.imageLoader.loadAndCacheImage(fileImageId); return image; })(); } static ɵfac = function VolumeLoaderService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VolumeLoaderService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: VolumeLoaderService, factory: VolumeLoaderService.ɵfac }); } /***/ }, /***/ 4508 /*!******************************************************************************!*\ !*** ./libs/data-access/src/lib/services/preferences/preferences.service.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PreferencesService: () => (/* binding */ PreferencesService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); const PREFERENCES_STORAGE_KEY = 'tvct.preferences'; /** * Generic localStorage-backed preferences store.. */ class PreferencesService { get() { try { const raw = localStorage.getItem(PREFERENCES_STORAGE_KEY); return raw ? JSON.parse(raw) : {}; } catch { return {}; } } patch(preferences) { try { const next = { ...this.get(), ...preferences }; localStorage.setItem(PREFERENCES_STORAGE_KEY, JSON.stringify(next)); } catch { // Ignore storage errors } } clear() { try { localStorage.removeItem(PREFERENCES_STORAGE_KEY); } catch { // Ignore storage errors } } static ɵfac = function PreferencesService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PreferencesService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: PreferencesService, factory: PreferencesService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 23974 /*!***************************************************************************!*\ !*** ./libs/data-access/src/lib/services/recent-work-sessions.service.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RecentWorkSessionsService: () => (/* binding */ RecentWorkSessionsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 69042); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/utils/constants */ 11280); /* harmony import */ var _db_work_session_work_session_database_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../db/work-session/work-session-database.service */ 17818); /* harmony import */ var _auth_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./auth.service */ 52807); /** * Tracks the last opened work sessions (capped at `MAX_RECENT_WORK_SESSIONS`). * Held in memory only and is cleared on sign-out so tabs can't leak into the next login. * Sessions whose local document is deleted are pruned automatically. */ class RecentWorkSessionsService { authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_auth_service__WEBPACK_IMPORTED_MODULE_8__.AuthService); destroyRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef); workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_db_work_session_work_session_database_service__WEBPACK_IMPORTED_MODULE_7__.WorkSessionDatabaseService); _sessions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "_sessions" }] : [])); sessions = this._sessions.asReadonly(); // Tracks when each session was last opened so eviction targets the least // recently opened tab while tab positions stay stable. Kept outside the // signal so re-opening an already tracked tab doesn't retrigger subscribers. lastOpenedSequence = new Map(); nextOpenedSequence = 0; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { if (this.authService.isAuthenticated()) return; this.lastOpenedSequence.clear(); this._sessions.set([]); }); // Watch each tracked session's local document and drop the tab when the // document disappears. The app is offline-first, so a recorded session // always exists locally and an absent document means it was deleted. // Removing a uid re-runs the switchMap without it, so the feedback into // `_sessions` settles after one pass. (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_1__.toObservable)(this._sessions).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.switchMap)(references => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.merge)(...references.map(reference => this.workSessionDb.get$(reference.workSessionUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_3__.filter)(session => !session), (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.map)(() => reference.workSessionUid))))), (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_1__.takeUntilDestroyed)(this.destroyRef)).subscribe(workSessionUid => this.remove(workSessionUid)); } /** * Register a session as opened. Already-tracked sessions keep their tab * position, new ones are appended. When full (MAX_RECENT_WORK_SESSIONS), * the least recently opened session is evicted. */ record(reference) { this.lastOpenedSequence.set(reference.workSessionUid, this.nextOpenedSequence++); const current = this._sessions(); if (current.some(session => session.workSessionUid === reference.workSessionUid)) return; let next = [...current, reference]; if (next.length > _tomoverse_utils_constants__WEBPACK_IMPORTED_MODULE_6__.MAX_RECENT_WORK_SESSIONS) { let evicted = reference; for (const session of next) { if (this.openedSequence(session) < this.openedSequence(evicted)) evicted = session; } this.lastOpenedSequence.delete(evicted.workSessionUid); next = next.filter(session => session !== evicted); } this._sessions.set(next); } remove(workSessionUid) { this.lastOpenedSequence.delete(workSessionUid); const current = this._sessions(); const next = current.filter(session => session.workSessionUid !== workSessionUid); if (next.length === current.length) return; this._sessions.set(next); } openedSequence(reference) { return this.lastOpenedSequence.get(reference.workSessionUid) ?? -1; } static ɵfac = function RecentWorkSessionsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RecentWorkSessionsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: RecentWorkSessionsService, factory: RecentWorkSessionsService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 29039 /*!************************************************************************************!*\ !*** ./libs/data-access/src/lib/services/work-session/work-session-api.service.ts ***! \************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionApiService: () => (/* binding */ WorkSessionApiService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils/injection-tokens/env-injection-token */ 42035); class WorkSessionApiService { http = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient); environment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_4__.ENV); apiUrl = `${this.environment.apiUrl}/v1/work-session`; get(_x) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (workSessionId, fullAttachments = false) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this.http.get(`${_this.apiUrl}/${workSessionId}`, { params: fullAttachments ? { fullAttachments: true } : {} })); }).apply(this, arguments); } find() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (filters = {}) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this2.http.get(_this2.apiUrl, { params: filters })); }).apply(this, arguments); } create(workSession) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this3.http.post(_this3.apiUrl, workSession)); })(); } update(workSessionId, workSession) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this4.http.put(`${_this4.apiUrl}/${workSessionId}`, workSession)); })(); } delete(workSessionId) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(_this5.http.delete(`${_this5.apiUrl}/${workSessionId}`)); })(); } static ɵfac = function WorkSessionApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionApiService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineInjectable"]({ token: WorkSessionApiService, factory: WorkSessionApiService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 60923 /*!*******************************************************************************************!*\ !*** ./libs/data-access/src/lib/services/work-session/work-session-navigation.service.ts ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionNavigationService: () => (/* binding */ WorkSessionNavigationService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../db/rxdb-manager.service */ 67189); class WorkSessionNavigationService { rxdbManager = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_db_rxdb_manager_service__WEBPACK_IMPORTED_MODULE_2__.RxdbManager); saveWorkSessionRequested = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "saveWorkSessionRequested" }] : [])); exportWorkSessionRequested = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "exportWorkSessionRequested" }] : [])); flushHandler; save() { this.saveWorkSessionRequested.update(v => v + 1); } export() { this.exportWorkSessionRequested.update(v => v + 1); } registerFlushHandler(handler) { this.flushHandler = handler; return () => { if (this.flushHandler === handler) this.flushHandler = undefined; }; } awaitPendingSync() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this.rxdbManager.awaitWorkSessionsInSync(); })(); } // Persists the live viewer state and waits for it to reach the backend. // Called before sign-out and window close; must never block them. flushPendingChanges() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { yield _this2.flushHandler?.(); yield _this2.awaitPendingSync(); } catch (error) { console.warn('Failed to flush pending work session changes', error); } })(); } static ɵfac = function WorkSessionNavigationService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionNavigationService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: WorkSessionNavigationService, factory: WorkSessionNavigationService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 99335 /*!***********************************************************************************!*\ !*** ./libs/data-access/src/lib/services/work-session/work-session-sse-client.ts ***! \***********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionSseClient: () => (/* binding */ WorkSessionSseClient) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 57417); class WorkSessionSseClient { stream(url, options = {}) { var _this = this; const { authProbe, getToken, keepAlive = true, reconnectionDelay = 3000, responseType = 'text' } = options; return new rxjs__WEBPACK_IMPORTED_MODULE_1__.Observable(subscriber => { let eventSource; let reconnectTimer; let isDestroyed = false; let isConnecting = false; const _connect = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (isDestroyed || isConnecting) return; isConnecting = true; try { yield authProbe?.(); } catch (error) { isConnecting = false; subscriber.error(new Error('Auth probe failed', { cause: error })); return; } if (isDestroyed) { isConnecting = false; return; } const authenticatedUrl = _this.buildUrl(url, getToken?.()); eventSource = new EventSource(authenticatedUrl); eventSource.addEventListener('message', event => _this.handleMessage(event, responseType, subscriber)); eventSource.addEventListener('error', error => { eventSource?.close(); if (keepAlive && !isDestroyed) { reconnectTimer = setTimeout(_connect, reconnectionDelay); } else { subscriber.error(error); } }); isConnecting = false; }); return function connect() { return _ref.apply(this, arguments); }; }(); _connect(); return () => { isDestroyed = true; clearTimeout(reconnectTimer); eventSource?.close(); }; }); } buildUrl(baseUrl, token) { if (!token) return baseUrl; const url = new URL(baseUrl, globalThis.location.origin); url.searchParams.set('access_token', token); return url.toString(); } handleMessage(event, type, subscriber) { try { const data = type === 'json' ? JSON.parse(event.data) : event.data; subscriber.next(data); } catch (error) { subscriber.error(new Error(`Failed to parse SSE message: ${error}`)); } } } /***/ }, /***/ 78210 /*!******************************************************************!*\ !*** ./libs/domain/src/lib/selectors/annotation-measurements.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getBatchMeasurements: () => (/* binding */ getBatchMeasurements), /* harmony export */ getMeasurements: () => (/* binding */ getMeasurements) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./annotation-selectors */ 66817); /* harmony import */ var _spline_selectors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spline-selectors */ 28713); function getBatchMeasurements(annotations, volume) { return Object.fromEntries(Object.entries(annotations).map(([id, annotation]) => { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationHasRelationship)(annotation)) { return [id, getMeasurements(annotation, volume, ...annotation.relationship.sourceIds.map(sId => annotations[sId]))]; } return [id, getMeasurements(annotation, volume)]; })); } // Passing in `IImageVolume` instead of raw voxel data for better memoization. const getMeasurements = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.memoizeByReference)((annotation, volume, ...parents) => { switch (annotation.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE: { return getAngleMeasurements(annotation); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE: { return getClosedSplineMeasurements(annotation); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CYLINDER: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.HOLLOW_CYLINDER: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.STL: { return getObject3DMeasurements(annotation); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE: { return getDistanceMeasurements(annotation); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE: { return getOpenSplineMeasurements(annotation, parents); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT: { return getPointMeasurements(annotation, volume, parents); } } }, // Can key by just `annotation` even though there are multiple args, // any changes to those will be caught in the reference check _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getId); function getAngleMeasurements(angle) { return [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.ANGLE, value: `${(0,_annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getAngle)(angle).toFixed(1).replace('.0', '')}°` }]; } function getPointMeasurements(point, volume, parents) { const position = (0,_annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getPosition)(point); const measurements = [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.POSITION, value: formatPosition(position) }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.PIXEL_VALUE, value: volume ? `${getVolumeValue(volume, point.position).toString()} HU` : '0 HU' }]; if (point.relationship?.type === 'curvature-point') { const spline = parents[0]; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsSpline)(spline)) { measurements.push({ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.POSITION_ALONG_SPLINE, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getDistanceAtPosition)(spline, position)) }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.RADIUS_OF_CURVATURE, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getCurvatureRadiusAtPosition)(spline, position)) }); } } return measurements; } function getClosedSplineMeasurements(spline) { const perimeter = (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getSplineLength)(spline); const pDerivedDiameter = perimeter / Math.PI; const area = (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getClosedSplineArea)(spline); const aDerivedDiameter = 2 * Math.sqrt(area / Math.PI); return [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.PERIMETER, value: `${formatMM(perimeter)} (⌀ ${formatMM(pDerivedDiameter)})` }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.AREA, value: `${formatMM(area)}² (⌀ ${formatMM(aDerivedDiameter)})` }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.MAXIMUM_DIAMETER, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getClosedSplineMaximumDiameter)(spline)) }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.HEIGHT, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getClosedSplineHeight)(spline)) }, { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.EN_FACE_VIEW, value: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.formatAngulationtxt)((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getClosedSplineEnFaceView)(spline), false) }]; } function getOpenSplineMeasurements(spline, parents) { const measurements = [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.LENGTH, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getSplineLength)(spline)) }]; if (spline.relationship?.type === 'attached-spline' && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsOpenSpline)(parents[0]) && spline.points[0]) { measurements.unshift({ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.BIFURCATION_POSITION, value: formatMM((0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getDistanceAtPosition)(parents[0], spline.points[0])) }); } return measurements; } function getDistanceMeasurements(distance) { return [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.DISTANCE, value: formatMM((0,_annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getDistance)(distance)) }]; } function getObject3DMeasurements(object3d) { return [{ name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.MeasurementName.EN_FACE_VIEW, value: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.formatAngulationtxt)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.angulationFromOrientation)(object3d.orientation), false) }]; } function getVolumeValue(volume, position) { try { const ijkCoords = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.worldToIndex)(volume, [...position]); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.getAtIJK)(volume, Math.round(ijkCoords[0]), Math.round(ijkCoords[1]), Math.round(ijkCoords[2])) ?? 0; } catch { // There are occasional race conditions where reads can fail return 0; } } function formatPosition(position) { const [x, y, z] = position; return `(${x.toFixed(1).replace('.0', '')}, ${y.toFixed(1).replace('.0', '')}, ${z.toFixed(1).replace('.0', '')}) mm`; } function formatMM(value) { return `${value.toFixed(1).replace('.0', '')} mm`; } /***/ }, /***/ 66817 /*!***************************************************************!*\ !*** ./libs/domain/src/lib/selectors/annotation-selectors.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getAngle: () => (/* binding */ getAngle), /* harmony export */ getCentroid: () => (/* binding */ getCentroid), /* harmony export */ getDistance: () => (/* binding */ getDistance), /* harmony export */ getDistanceNormal: () => (/* binding */ getDistanceNormal), /* harmony export */ getId: () => (/* binding */ getId), /* harmony export */ getNormal: () => (/* binding */ getNormal), /* harmony export */ getPath: () => (/* binding */ getPath), /* harmony export */ getPosition: () => (/* binding */ getPosition), /* harmony export */ getValid: () => (/* binding */ getValid), /* harmony export */ isRenderable: () => (/* binding */ isRenderable) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _spline_selectors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spline-selectors */ 28713); /** * Return the centroid of the provided annotation. * @param annotation * @returns */ function getCentroid(annotation) { if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.POINT) { return annotation.position; } if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.DISTANCE) { const [start, end] = annotation.points; return [(start[0] + end[0]) / 2, (start[1] + end[1]) / 2, (start[2] + end[2]) / 2]; } if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.ANGLE) { return (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getTriangleCentroid)(annotation.points); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsSpline)(annotation)) { return (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getSplineCentroid)(annotation); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsObject3D)(annotation)) { return annotation.position; } return [0, 0, 0]; } function getNormal(annotation) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationHasPoints)(annotation)) { const points = annotation.points; if (points.length < 3) { return getDistanceNormal(points[0], points[1]); } const p0 = points[0]; let nx = 0, ny = 0, nz = 0; for (let index = 1; index < points.length - 1; index++) { const [p1, p2] = [points[index], points[index + 1]]; if (!p1 || !p2 || !p0) continue; // Vectors from p0 const v1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]); const v2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]); // Cross product v1 × v2 const cross = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(cross, v1, v2); nx += cross[0]; ny += cross[1]; nz += cross[2]; } // Normalize the result const length = Math.hypot(nx, ny, nz); if (length === 0) { throw new Error('Points do not form a valid plane'); } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.position)(nx / length, ny / length, nz / length); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsObject3D)(annotation)) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.object3dSymmetryAxis)(annotation.orientation, (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsStl)(annotation) ? annotation.axisOfSymmetryRotation : undefined); } return undefined; } function getDistanceNormal(p0, p1) { // direction vector const direction = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]); const directionLength = Math.hypot(direction[0], direction[1], direction[2]); if (directionLength === 0) { throw new Error('Points must be different'); } // Normalize direction const d = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(direction[0] / directionLength, direction[1] / directionLength, direction[2] / directionLength); // choose a reference vector not parallel to d let reference = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(0, 0, 1); const dot = d[0] * reference[0] + d[1] * reference[1] + d[2] * reference[2]; if (Math.abs(dot) > 0.9) { reference = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(0, 1, 0); } // cross product → perpendicular const perp = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(perp, d, reference); // Step 4: normalize result const length = Math.hypot(perp[0], perp[1], perp[2]); return [perp[0] / length, perp[1] / length, perp[2] / length]; } /** * Return the position of the provided annotation. * @param annotation * @returns */ function getPosition(annotation) { return annotation.position; } /** * Return the id of the provided annotation. * @param annotation * @returns */ function getId(annotation) { return annotation.id; } /** * Return the distance value between a Distance's start and end points. */ const getDistance = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(distance => { const [start, end] = distance.points; if (start === undefined || end === undefined) { return 0; } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateDistanceBetweenPoints)(start, end); }, getId); /** * Return the angle value between an Angle's line [a, b] and [b, c] line segments. */ const getAngle = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(angle => { const [start, center, end] = angle.points; if (!start || !center || !end) { return 0; } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateAngleBetweenPoints)(start, center, end); }, getId); /** * Return whether the provided annotation is valid, eg. whether it is * complete and can be added to the collection. */ // eslint-disable-next-line sonarjs/cyclomatic-complexity function getValid(annotation) { switch (annotation.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.ANGLE: { return annotation.points.length === 3; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.CLOSED_SPLINE: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.OPEN_SPLINE: { return annotation.points.length > 1; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.CYLINDER: { return annotation.diameter > 0 && annotation.height > 0 && annotation.sides >= 3 && isFiniteQuat(annotation.orientation) && isFinitePosition(annotation.position); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.DISTANCE: { return annotation.points.length === 2; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.HOLLOW_CYLINDER: { return annotation.height > 0 && annotation.innerDiameter > 0 && annotation.outerDiameter > annotation.innerDiameter && annotation.sides >= 3 && isFiniteQuat(annotation.orientation) && isFinitePosition(annotation.position); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.POINT: { return true; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.STL: { return annotation.fileName.length > 0 && isFiniteQuat(annotation.orientation) && annotation.axisOfSymmetryRotation.length === 16 && annotation.axisOfSymmetryRotation.every(element => Number.isFinite(element)) && isFinitePosition(annotation.position); } } } /** * Return whether the provided annotation is able to be rendered correctly. * @param annotation * @returns */ const isRenderable = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(annotation => { // Uninitialized points are generally present in incomplete annotation, // or certain invalid states (eg. "Angle between splines" with parallel splines.) if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationHasPoints)(annotation)) { return !annotation.points.some(point => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.positionIsUninitialized)(point)); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationHasPosition)(annotation)) { return !(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.positionIsUninitialized)(annotation.position); } return true; }, getId); const getPath = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(annotation => { switch (annotation.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.ANGLE: { const [start, middle, end] = annotation.points; if (!start || !middle || !end) { return annotation.points; } const pathA = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateSplinePath)([start, middle], false); const [, ...pathB] = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateSplinePath)([middle, end], false); return [...pathA, ...pathB]; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.CLOSED_SPLINE: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.OPEN_SPLINE: { return (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_4__.getSplinePath)(annotation); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.DISTANCE: { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateSplinePath)(annotation.points, false); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.POINT: { return [annotation.position]; } default: { return []; } } }, getId); function isFiniteQuat(q) { return q.length === 4 && q.every(element => Number.isFinite(element)); } function isFinitePosition(p) { return p.length === 3 && p.every(element => Number.isFinite(element)); } /***/ }, /***/ 26172 /*!****************************************************************!*\ !*** ./libs/domain/src/lib/selectors/dicom-store-selectors.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STORE_TYPE_ORDER: () => (/* binding */ STORE_TYPE_ORDER), /* harmony export */ storeTypeForVendor: () => (/* binding */ storeTypeForVendor) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /** Fixed display order of store groups in store-selector menus. */ const STORE_TYPE_ORDER = [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.StoreType.CLOUD, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.StoreType.DIMSE, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.StoreType.DICOM_WEB]; /** * Connection category for a vendor. */ function storeTypeForVendor(vendor) { switch (vendor) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomVendor.GOOGLE_HEALTHCARE: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomVendor.ORTHANC: { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.StoreType.DICOM_WEB; } } } /***/ }, /***/ 27531 /*!************************************************!*\ !*** ./libs/domain/src/lib/selectors/index.ts ***! \************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STORE_TYPE_ORDER: () => (/* reexport safe */ _dicom_store_selectors__WEBPACK_IMPORTED_MODULE_2__.STORE_TYPE_ORDER), /* harmony export */ canPlaceholderBeAutocreated: () => (/* reexport safe */ _placeholder_selectors__WEBPACK_IMPORTED_MODULE_4__.canPlaceholderBeAutocreated), /* harmony export */ canPlaceholderBeCompleted: () => (/* reexport safe */ _placeholder_selectors__WEBPACK_IMPORTED_MODULE_4__.canPlaceholderBeCompleted), /* harmony export */ canProceedFromProtocolForm: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.canProceedFromProtocolForm), /* harmony export */ compareBy: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.compareBy), /* harmony export */ compareValues: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.compareValues), /* harmony export */ createAnnotationFromPlaceholder: () => (/* reexport safe */ _placeholder_selectors__WEBPACK_IMPORTED_MODULE_4__.createAnnotationFromPlaceholder), /* harmony export */ filterStudies: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.filterStudies), /* harmony export */ getAngle: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getAngle), /* harmony export */ getBatchMeasurements: () => (/* reexport safe */ _annotation_measurements__WEBPACK_IMPORTED_MODULE_1__.getBatchMeasurements), /* harmony export */ getCentroid: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getCentroid), /* harmony export */ getClosedSplineArea: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getClosedSplineArea), /* harmony export */ getClosedSplineEnFaceView: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getClosedSplineEnFaceView), /* harmony export */ getClosedSplineHeight: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getClosedSplineHeight), /* harmony export */ getClosedSplineMaximumDiameter: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getClosedSplineMaximumDiameter), /* harmony export */ getCurvatureRadiusAtPosition: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getCurvatureRadiusAtPosition), /* harmony export */ getDistance: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getDistance), /* harmony export */ getDistanceAtPosition: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getDistanceAtPosition), /* harmony export */ getDistanceNormal: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getDistanceNormal), /* harmony export */ getGeometryOctree: () => (/* reexport safe */ _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__.getGeometryOctree), /* harmony export */ getId: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getId), /* harmony export */ getMeasurements: () => (/* reexport safe */ _annotation_measurements__WEBPACK_IMPORTED_MODULE_1__.getMeasurements), /* harmony export */ getNextPlaceholder: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.getNextPlaceholder), /* harmony export */ getNormal: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getNormal), /* harmony export */ getObject3DGeometry: () => (/* reexport safe */ _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DGeometry), /* harmony export */ getObject3DOctree: () => (/* reexport safe */ _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DOctree), /* harmony export */ getObject3DTransformMatrix: () => (/* reexport safe */ _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DTransformMatrix), /* harmony export */ getPath: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getPath), /* harmony export */ getPosition: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getPosition), /* harmony export */ getPreviousPlaceholder: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.getPreviousPlaceholder), /* harmony export */ getSCurveAngleDegrees: () => (/* reexport safe */ _s_curve_relative_measurement_selectors__WEBPACK_IMPORTED_MODULE_6__.getSCurveAngleDegrees), /* harmony export */ getSCurveEnFaceAngle: () => (/* reexport safe */ _s_curve_selectors__WEBPACK_IMPORTED_MODULE_7__.getSCurveEnFaceAngle), /* harmony export */ getSCurveIntersectionAngulation: () => (/* reexport safe */ _s_curve_relative_measurement_selectors__WEBPACK_IMPORTED_MODULE_6__.getSCurveIntersectionAngulation), /* harmony export */ getSCurveIntersectionPosition: () => (/* reexport safe */ _s_curve_relative_measurement_selectors__WEBPACK_IMPORTED_MODULE_6__.getSCurveIntersectionPosition), /* harmony export */ getSCurvePath: () => (/* reexport safe */ _s_curve_selectors__WEBPACK_IMPORTED_MODULE_7__.getSCurvePath), /* harmony export */ getSCurveSvgPath: () => (/* reexport safe */ _s_curve_selectors__WEBPACK_IMPORTED_MODULE_7__.getSCurveSvgPath), /* harmony export */ getSplineBestFitNormal: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getSplineBestFitNormal), /* harmony export */ getSplineCentroid: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getSplineCentroid), /* harmony export */ getSplineLength: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getSplineLength), /* harmony export */ getSplinePath: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getSplinePath), /* harmony export */ getTriangleCentroid: () => (/* reexport safe */ _spline_selectors__WEBPACK_IMPORTED_MODULE_8__.getTriangleCentroid), /* harmony export */ getValid: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.getValid), /* harmony export */ inDateRange: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.inDateRange), /* harmony export */ isProtocolComplete: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.isProtocolComplete), /* harmony export */ isProtocolEmpty: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.isProtocolEmpty), /* harmony export */ isProtocolFormValid: () => (/* reexport safe */ _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__.isProtocolFormValid), /* harmony export */ isRenderable: () => (/* reexport safe */ _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__.isRenderable), /* harmony export */ matchesAnyOf: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.matchesAnyOf), /* harmony export */ matchesReviewStatus: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.matchesReviewStatus), /* harmony export */ matchesText: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.matchesText), /* harmony export */ snapPositionToObject3D: () => (/* reexport safe */ _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__.snapPositionToObject3D), /* harmony export */ sortRows: () => (/* reexport safe */ _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__.sortRows), /* harmony export */ storeTypeForVendor: () => (/* reexport safe */ _dicom_store_selectors__WEBPACK_IMPORTED_MODULE_2__.storeTypeForVendor) /* harmony export */ }); /* harmony import */ var _annotation_selectors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-selectors */ 66817); /* harmony import */ var _annotation_measurements__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./annotation-measurements */ 78210); /* harmony import */ var _dicom_store_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./dicom-store-selectors */ 26172); /* harmony import */ var _object3d_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./object3d-selectors */ 90180); /* harmony import */ var _placeholder_selectors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./placeholder-selectors */ 20333); /* harmony import */ var _protocol_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./protocol-selectors */ 47536); /* harmony import */ var _s_curve_relative_measurement_selectors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./s-curve-relative-measurement-selectors */ 80263); /* harmony import */ var _s_curve_selectors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./s-curve-selectors */ 95823); /* harmony import */ var _spline_selectors__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./spline-selectors */ 28713); /* harmony import */ var _study_search_selectors__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./study-search-selectors */ 96964); /***/ }, /***/ 90180 /*!*************************************************************!*\ !*** ./libs/domain/src/lib/selectors/object3d-selectors.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getGeometryOctree: () => (/* binding */ getGeometryOctree), /* harmony export */ getObject3DGeometry: () => (/* binding */ getObject3DGeometry), /* harmony export */ getObject3DOctree: () => (/* binding */ getObject3DOctree), /* harmony export */ getObject3DTransformMatrix: () => (/* binding */ getObject3DTransformMatrix), /* harmony export */ snapPositionToObject3D: () => (/* binding */ snapPositionToObject3D) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_selectors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./annotation-selectors */ 66817); const getObject3DGeometry = (() => { let stlFetcher; const memo = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(annotation => { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.annotationIsCylinder)(annotation)) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.withShell)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateCylinderGeometry)(annotation.diameter / 2, annotation.height, annotation.sides)); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.annotationIsHollowCylinder)(annotation)) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.withShell)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateHollowCylinderGeometry)(annotation.innerDiameter / 2, annotation.outerDiameter / 2, annotation.height, annotation.sides)); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.annotationIsStl)(annotation) && stlFetcher) { return stlFetcher(annotation); } throw new Error('Unsupported geometry request'); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_4__.getId); // eslint-disable-next-line @typescript-eslint/no-explicit-any memo.setStlFetcher = fetcher => { stlFetcher = fetcher; }; return memo; })(); const getObject3DOctree = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(annotation => { const geometry = getObject3DGeometry(annotation); return getGeometryOctree(geometry); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_4__.getId); // NOTE: We want to memoize at the Geometry level instead of Annotation because otherwise // we are going to rebuild the octree any time the annotation changes (movement, rotation, etc) const getGeometryOctree = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(geometry => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.buildOctree)(geometry)); function snapPositionToObject3D(point, geometry, geometryTransform, octree) { // Apply inverse translation/rotation to point so it is // local to the geometry const localPoint = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat4(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), point, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.invert(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), geometryTransform)); const projectedPoint = octree ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.projectPointOnOctree)(localPoint, geometry, octree) : (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.projectPointOnGeometry)(localPoint, geometry); // Bring the projected point back into world space. gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat4(projectedPoint, projectedPoint, geometryTransform); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.vec3ToPosition)(projectedPoint); } const getObject3DTransformMatrix = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.memoizeByReference)(object3d => { const geometry = getObject3DGeometry(object3d); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.buildObject3dTransform)(object3d, geometry.centroid); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_4__.getId); /***/ }, /***/ 20333 /*!****************************************************************!*\ !*** ./libs/domain/src/lib/selectors/placeholder-selectors.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ canPlaceholderBeAutocreated: () => (/* binding */ canPlaceholderBeAutocreated), /* harmony export */ canPlaceholderBeCompleted: () => (/* binding */ canPlaceholderBeCompleted), /* harmony export */ createAnnotationFromPlaceholder: () => (/* binding */ createAnnotationFromPlaceholder) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Determines whether a placeholder's annotation can be created automatically, * based on the presence of a relationship and the type of relationship. */ function canPlaceholderBeAutocreated(placeholder) { switch (placeholder.relationship?.type) { // These relationship types require no user input case 'angle-between-spline-axes': case 'angle-between-splines': case 'closest-distance-between-annotations': case 'distance-between': case 'projected-distance-from-point': { return true; } default: { return false; } } } /** * Returns true if the all the placeholder's source annotations are available */ function canPlaceholderBeCompleted(placeholder, instance) { if (placeholder.relationship === undefined) { return true; } return placeholder.relationship.sourceIds.every(sourceId => !!instance.placeholderMappings[sourceId]); } function createAnnotationFromPlaceholder(placeholder, protocolInstance) { const base = { color: placeholder.color, hidden: false, name: placeholder.name }; switch (placeholder.annotationType) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE: { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.angle)({ ...base, points: relationshipPoints(placeholder), relationship: mapRelationship(placeholder.relationship, protocolInstance.placeholderMappings) }); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE: { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.closedSpline)({ ...base, points: relationshipPoints(placeholder) }); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE: { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.distance)({ ...base, points: relationshipPoints(placeholder), relationship: mapRelationship(placeholder.relationship, protocolInstance.placeholderMappings) }); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE: { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.openSpline)({ ...base, points: relationshipPoints(placeholder), relationship: mapRelationship(placeholder.relationship, protocolInstance.placeholderMappings) }); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT: { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.point)({ ...base, position: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, relationship: mapRelationship(placeholder.relationship, protocolInstance.placeholderMappings) }); } default: { return; } } } function mapRelationship(relationship, mappings) { if (!relationship) return undefined; return { ...relationship, sourceIds: relationship.sourceIds.map(id => mappings[id] ?? '') }; } // eslint-disable-next-line sonarjs/cyclomatic-complexity function relationshipPoints(placeholder) { if (!placeholder || !hasSourceIds(placeholder.relationship)) { return []; } switch (placeholder?.relationship?.type) { case 'angle-between-spline-axes': case 'angle-between-splines': { return [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT]; } case 'attached-distance': case 'attached-spline': case 'closest-distance-between-annotations': case 'projected-distance-from-point': { return [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT]; } case 'center-distance': case 'closest-distance-to-one-annotation': case 'projected-distance': { return [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT]; } default: { return []; } } } function hasSourceIds(relationship) { return typeof relationship === 'object' && relationship !== null && 'sourceIds' in relationship; } /***/ }, /***/ 47536 /*!*************************************************************!*\ !*** ./libs/domain/src/lib/selectors/protocol-selectors.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ canProceedFromProtocolForm: () => (/* binding */ canProceedFromProtocolForm), /* harmony export */ getNextPlaceholder: () => (/* binding */ getNextPlaceholder), /* harmony export */ getPreviousPlaceholder: () => (/* binding */ getPreviousPlaceholder), /* harmony export */ isProtocolComplete: () => (/* binding */ isProtocolComplete), /* harmony export */ isProtocolEmpty: () => (/* binding */ isProtocolEmpty), /* harmony export */ isProtocolFormValid: () => (/* binding */ isProtocolFormValid) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _validators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../validators */ 74208); /* harmony import */ var _placeholder_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./placeholder-selectors */ 20333); function isProtocolComplete(definition, instance) { if (definition.id !== instance?.protocolId) return false; // TODO: Maybe also ensure the annotation exists? return definition.placeholders.every(placeholder => instance.placeholderMappings[placeholder.id] !== undefined); } function isProtocolEmpty(instance) { return Object.keys(instance?.placeholderMappings ?? {}).length === 0; } /** * Returns the next placeholder in the protocol that has not been filled * and has all the prerequisite sources, if it is a relative measurement. */ function getNextPlaceholder(definition, instance, { afterPlaceholderId, loopBack = false, prioritizeAutoCreate = false } = {}) { if (instance && definition.id !== instance.protocolId) return; const afterIndex = afterPlaceholderId ? definition.placeholders.findIndex(({ id }) => id === afterPlaceholderId) : -1; // If there is a placeholder that can be autocreated, // that always comes first if (prioritizeAutoCreate) { const toAutocreate = definition.placeholders.find((placeholder, index) => { // Skip any placeholders that can't be autocreated if (!(0,_placeholder_selectors__WEBPACK_IMPORTED_MODULE_2__.canPlaceholderBeAutocreated)(placeholder)) { return false; } // If `afterPlaceholderId` was provided, skip entries before it if (index <= afterIndex) { return false; } // Skip placeholders that have already been filled if (instance?.placeholderMappings[placeholder.id] !== undefined) { return false; } // Return if all sources are available for creation return placeholder.relationship && placeholder.relationship.sourceIds.every(sourceId => instance?.placeholderMappings[sourceId] !== undefined); }); if (toAutocreate !== undefined) { return toAutocreate; } } const next = definition.placeholders.find((placeholder, index) => { // If `afterPlaceholderId` was provided, skip entries before it if (index <= afterIndex) { return false; } // Skip placeholders that have already been filled if (instance?.placeholderMappings[placeholder.id] !== undefined) { return false; } // Skip relative measurements without their sources if (placeholder.relationship) { return placeholder.relationship.sourceIds.every(sourceId => instance?.placeholderMappings[sourceId] !== undefined); } return true; }); if (next === undefined && loopBack && afterPlaceholderId !== undefined) { return getNextPlaceholder(definition, instance, { afterPlaceholderId: undefined, loopBack: false, prioritizeAutoCreate }); } return next; } function getPreviousPlaceholder(definition, instance, currentId, { loopBack = true } = {}) { if (definition.id !== instance.protocolId) return; const currentIndex = currentId ? definition.placeholders.findIndex(({ id }) => id === currentId) : -1; const previous = definition.placeholders.findLast((placeholder, index) => index < currentIndex && !(0,_placeholder_selectors__WEBPACK_IMPORTED_MODULE_2__.canPlaceholderBeAutocreated)(placeholder) && instance.placeholderMappings[placeholder.id] !== undefined); if (previous === undefined && loopBack) { return definition.placeholders.findLast((placeholder, index) => index > currentIndex && !(0,_placeholder_selectors__WEBPACK_IMPORTED_MODULE_2__.canPlaceholderBeAutocreated)(placeholder) && instance.placeholderMappings[placeholder.id] !== undefined); } return previous; } function isProtocolFormValid(formDefinition, formValues) { // No form to validate if (formDefinition === undefined) { return true; } if (formValues === undefined) { return false; } return (0,_validators__WEBPACK_IMPORTED_MODULE_1__.validateProtocolForm)(formDefinition.validation, formValues).valid; } function canProceedFromProtocolForm(formDefinition, formValues) { if (formDefinition?.required === true) { if (!isProtocolFormValid(formDefinition, formValues)) { return false; } if (formDefinition.canProceedRule) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isPass)((0,_validators__WEBPACK_IMPORTED_MODULE_1__.validateProtocolFormField)(formDefinition.canProceedRule, 'form', formValues ?? {})); } } return true; } /***/ }, /***/ 80263 /*!*********************************************************************************!*\ !*** ./libs/domain/src/lib/selectors/s-curve-relative-measurement-selectors.ts ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getSCurveAngleDegrees: () => (/* binding */ getSCurveAngleDegrees), /* harmony export */ getSCurveIntersectionAngulation: () => (/* binding */ getSCurveIntersectionAngulation), /* harmony export */ getSCurveIntersectionPosition: () => (/* binding */ getSCurveIntersectionPosition) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _s_curve_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./s-curve-selectors */ 95823); const resolveByIds = (a, b) => `${a.id}:${b.id}`; /** * Returns the angle (in degrees, always within [0, 90]) between two s-curves, * derived from the cross-plane angle between their defining direction vectors. */ const getSCurveAngleDegrees = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.memoizeByReference)((a, b) => { const v1 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)((0,_s_curve_selectors__WEBPACK_IMPORTED_MODULE_2__.getSCurveEnFaceAngle)(a)); const v2 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)((0,_s_curve_selectors__WEBPACK_IMPORTED_MODULE_2__.getSCurveEnFaceAngle)(b)); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.rad2deg)(Math.acos((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.clampRange)(Math.abs(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(v1, v2)), -1, 1))); }, resolveByIds); // Below this, the cross product is too close to the zero vector to normalize // into a meaningful direction (parallel/antipodal en-face vectors - no single // intersection direction is defined). const MIN_CROSS_PRODUCT_SQUARED_LENGTH = 1e-10; /** * Flips a normalized direction vector into a canonical hemisphere (z, then y, * then x tie-broken non-negative) in place. cross(a, b) === -cross(b, a), so * without this, swapping the source-curve order would flip which of the two * antipodal directions is returned - this makes the result order-independent. */ function canonicalizeAxisSign(vector) { const x = vector[0]; const y = vector[1]; const z = vector[2]; const isNegativeHemisphere = z < 0 || z === 0 && (y < 0 || y === 0 && x < 0); if (isNegativeHemisphere) gl_matrix__WEBPACK_IMPORTED_MODULE_0__.negate(vector, vector); } /** * Returns the angulation at which two s-curves intersect, derived from the * (normalized) cross product of their defining direction vectors. Returns * `undefined` when the curves' en-face directions are parallel or antipodal, * since no single intersection direction exists in that case. */ const getSCurveIntersectionAngulation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.memoizeByReference)((a, b) => { const v1 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)((0,_s_curve_selectors__WEBPACK_IMPORTED_MODULE_2__.getSCurveEnFaceAngle)(a)); const v2 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)((0,_s_curve_selectors__WEBPACK_IMPORTED_MODULE_2__.getSCurveEnFaceAngle)(b)); const n3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), v1, v2); if (gl_matrix__WEBPACK_IMPORTED_MODULE_0__.squaredLength(n3) < MIN_CROSS_PRODUCT_SQUARED_LENGTH) return; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n3, n3); canonicalizeAxisSign(n3); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(n3)); }, resolveByIds); /** * Returns the graph position ([rl, cc]) at which two s-curves intersect, or * `undefined` when no single intersection direction exists (see * `getSCurveIntersectionAngulation`). */ function getSCurveIntersectionPosition(a, b) { const angulation = getSCurveIntersectionAngulation(a, b); if (!angulation) return undefined; const { cc, rl } = angulation; return [rl, cc]; } /***/ }, /***/ 95823 /*!************************************************************!*\ !*** ./libs/domain/src/lib/selectors/s-curve-selectors.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getSCurveEnFaceAngle: () => (/* binding */ getSCurveEnFaceAngle), /* harmony export */ getSCurvePath: () => (/* binding */ getSCurvePath), /* harmony export */ getSCurveSvgPath: () => (/* binding */ getSCurveSvgPath) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotation-selectors */ 66817); /* harmony import */ var _spline_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./spline-selectors */ 28713); // Making this number larger will make rendering faster at the expense of resolution // The educational version uses 2 const CURVE_PATH_STEP = 2; /** * Generates an SVG-ready path for the given S-Curve. */ const getSCurveSvgPath = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.memoizeByReference)(curve => { const points = getSCurvePath(curve); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.buildSvgPath)(points); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getId); const getSCurveEnFaceAngle = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.memoizeByReference)(scurve => { switch (scurve.type) { case 'control-point': { const [one, two] = scurve.controlPoints; if (one !== undefined && two !== undefined) { const [rl1, cc1] = one; const [rl2, cc2] = two; const n1 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)({ ax: 0, cc: cc1, rl: rl1 }); const n2 = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationToVector)({ ax: 0, cc: cc2, rl: rl2 }); const n3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), n1, n2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n3, n3); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(n3)); } else if (one === undefined) { console.warn('Invalid number of control points found'); return { ax: 0, cc: 0, rl: 0 }; } else { const [rl, cc] = one; return { ax: 0, cc, rl }; } } case 'spline': { return (0,_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getClosedSplineEnFaceView)(scurve.spline); } } }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getId); const getSCurvePath = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.memoizeByReference)(curve => { const path = []; const angle = getSCurveEnFaceAngle(curve); for (let rl = -90; rl <= 90; rl += CURVE_PATH_STEP) { const cc = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.sCurvePointOnPath)(rl, angle); path.push([rl, cc]); } // We need to interpolate by a fixed distance so that we can smoothly // move along very steep parts of the path. return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.linearInterpolationByDistance2D)(path, 0.5); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getId); /***/ }, /***/ 28713 /*!***********************************************************!*\ !*** ./libs/domain/src/lib/selectors/spline-selectors.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getClosedSplineArea: () => (/* binding */ getClosedSplineArea), /* harmony export */ getClosedSplineEnFaceView: () => (/* binding */ getClosedSplineEnFaceView), /* harmony export */ getClosedSplineHeight: () => (/* binding */ getClosedSplineHeight), /* harmony export */ getClosedSplineMaximumDiameter: () => (/* binding */ getClosedSplineMaximumDiameter), /* harmony export */ getCurvatureRadiusAtPosition: () => (/* binding */ getCurvatureRadiusAtPosition), /* harmony export */ getDistanceAtPosition: () => (/* binding */ getDistanceAtPosition), /* harmony export */ getSplineBestFitNormal: () => (/* binding */ getSplineBestFitNormal), /* harmony export */ getSplineCentroid: () => (/* binding */ getSplineCentroid), /* harmony export */ getSplineLength: () => (/* binding */ getSplineLength), /* harmony export */ getSplinePath: () => (/* binding */ getSplinePath), /* harmony export */ getTriangleCentroid: () => (/* binding */ getTriangleCentroid) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./annotation-selectors */ 66817); const getSplinePath = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.memoizeByReference)(spline => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateSplinePath)(spline.points, (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(spline)), _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getId); const getSplineCentroid = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.memoizeByReference)(spline => { const path = getSplinePath(spline); const length = path.length; const c = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); const v = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); for (const point of path) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(v, point[0] / length, point[1] / length, point[2] / length); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(c, c, v); } return [c[0], c[1], c[2]]; }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getId); const getTriangleCentroid = points => { const [p0, p1, p2] = points; return [(p0[0] + p1[0] + p2[0]) / 3, (p0[1] + p1[1] + p2[1]) / 3, (p0[2] + p1[2] + p2[2]) / 3]; }; const getSplineBestFitNormal = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.memoizeByReference)(spline => { const path = getSplinePath(spline); const centroid = getSplineCentroid.unmemoized(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateClosedSplineBestFitNormal)(path, centroid); }, _annotation_selectors__WEBPACK_IMPORTED_MODULE_3__.getId); // NOTE: Currently only used in measurements (which are memoized), // so we'll keep the following functions unmemoized function getClosedSplineEnFaceView(spline) { const bestFitNormal = getSplineBestFitNormal(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.vectorToAngulation)(bestFitNormal); } function getClosedSplineArea(spline) { const path = getSplinePath(spline); const centroid = getSplineCentroid(spline); const bestFitNormal = getSplineBestFitNormal(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateClosedSplineArea)(path, centroid, bestFitNormal); } function getClosedSplineHeight(spline) { const path = getSplinePath(spline); const centroid = getSplineCentroid(spline); const bestFitNormal = getSplineBestFitNormal(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateClosedSplineHeight)(path, centroid, bestFitNormal); } function getClosedSplineMaximumDiameter(spline) { const path = getSplinePath(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculatePathMaximumDiameter)(path); } function getDistanceAtPosition(spline, position) { const path = getSplinePath(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateDistanceOnPath)(path, position); } function getCurvatureRadiusAtPosition(spline, position) { const path = getSplinePath(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculateCurvatureRadius)(path, position); } function getSplineLength(spline) { const path = getSplinePath(spline); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.calculatePathDistance)(path, (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(spline)); } /***/ }, /***/ 96964 /*!*****************************************************************!*\ !*** ./libs/domain/src/lib/selectors/study-search-selectors.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ compareBy: () => (/* binding */ compareBy), /* harmony export */ compareValues: () => (/* binding */ compareValues), /* harmony export */ filterStudies: () => (/* binding */ filterStudies), /* harmony export */ inDateRange: () => (/* binding */ inDateRange), /* harmony export */ matchesAnyOf: () => (/* binding */ matchesAnyOf), /* harmony export */ matchesReviewStatus: () => (/* binding */ matchesReviewStatus), /* harmony export */ matchesText: () => (/* binding */ matchesText), /* harmony export */ sortRows: () => (/* binding */ sortRows) /* harmony export */ }); /** Case-insensitive substring match. An empty/undefined term means "no filter". */ function matchesText(value, term) { if (!term) return true; return (value ?? '').toLowerCase().includes(term.toLowerCase()); } /** Any-overlap match: the row's value list intersects the allowed list. Empty/undefined list means "no filter". */ function matchesAnyOf(values, allowed) { if (!allowed || allowed.length === 0) return true; return values.some(value => allowed.includes(value)); } /** Exact review-status match. No wanted status means "no filter". */ function matchesReviewStatus(value, wanted) { return !wanted || value === wanted; } /** Inclusive DICOM YYYYMMDD range match (lexical = chronological). */ function inDateRange(value, from, to) { if (!from && !to) return true; if (!value) return false; return (!from || value >= from) && (!to || value <= to); } /** Reads a possibly-dotted path off a row. */ function readPath(row, path) { let current = row; for (const key of path.split('.')) { if (!current || typeof current !== 'object') return; current = current[key]; } return current; } /** Null-safe compare. `0`/`false` are real values, numeric when both numbers. */ function compareValues(a, b) { if (a == undefined && b == undefined) return 0; if (a == undefined) return -1; if (b == undefined) return 1; if (typeof a === 'number' && typeof b === 'number') return a - b; return String(a).localeCompare(String(b)); } /** Comparator for a `SortSpec` over rows. */ function compareBy(sort) { return (a, b) => compareValues(readPath(a, sort.field), readPath(b, sort.field)) * sort.direction; } /** Immutable sort. Returns the rows unchanged when no sort is requested (native order). */ function sortRows(rows, sort) { return sort ? rows.toSorted(compareBy(sort)) : [...rows]; } /** Filters study rows by the (substring, modality list, and date-range) criteria. */ function filterStudies(rows, criteria) { return rows.filter(row => { const matchesTextCriteria = matchesText(row.patientName, criteria.patientName) && matchesText(row.patientID, criteria.patientID) && matchesText(row.studyDescription, criteria.description) && matchesText(row.institutionName, criteria.institution); return matchesTextCriteria && matchesAnyOf(row.modalities, criteria.modalities) && inDateRange(row.studyDate, criteria.studyDateFrom, criteria.studyDateTo) && matchesReviewStatus(row.reviewStatus, criteria.reviewStatus); }); } /***/ }, /***/ 77939 /*!*************************************************************!*\ !*** ./libs/domain/src/lib/updaters/annotation-updaters.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ addPointAt: () => (/* binding */ addPointAt), /* harmony export */ appendPoint: () => (/* binding */ appendPoint), /* harmony export */ changeColor: () => (/* binding */ changeColor), /* harmony export */ clone: () => (/* binding */ clone), /* harmony export */ hide: () => (/* binding */ hide), /* harmony export */ move: () => (/* binding */ move), /* harmony export */ movePoint: () => (/* binding */ movePoint), /* harmony export */ prependPoint: () => (/* binding */ prependPoint), /* harmony export */ removePointAt: () => (/* binding */ removePointAt), /* harmony export */ rename: () => (/* binding */ rename), /* harmony export */ resetOrientation: () => (/* binding */ resetOrientation), /* harmony export */ rotateAboutAxis: () => (/* binding */ rotateAboutAxis), /* harmony export */ setAxisOfSymmetryRotation: () => (/* binding */ setAxisOfSymmetryRotation), /* harmony export */ setCenterOfRotation: () => (/* binding */ setCenterOfRotation), /* harmony export */ setOrientation: () => (/* binding */ setOrientation), /* harmony export */ setPlaceholderId: () => (/* binding */ setPlaceholderId), /* harmony export */ setPoints: () => (/* binding */ setPoints), /* harmony export */ show: () => (/* binding */ show), /* harmony export */ toggleLock: () => (/* binding */ toggleLock) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 85648); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! uuid */ 69083); /** * Return a copy of the provided annotation with the specified point * added to the point list at the specified index. * @param annotation The annotation to update * @param pointIndex The index to add the new point at * @param position The position of the new point * @returns Updated copy of the annotation with the new point */ function addPointAt(annotation, pointIndex, position) { const points = [...annotation.points]; points.splice(pointIndex, 0, position); return { ...annotation, points }; } /** * Return a copy of the provided annotation with a point removed * removed from the point list at the specified index. * @param annotation The annotation to update * @param pointIndex The index toe remove the point from * @returns Updated copy of the annotation with the removed point */ function removePointAt(annotation, pointIndex) { if (annotation.points.length < pointIndex) return annotation; return { ...annotation, points: annotation.points.toSpliced(pointIndex, 1) }; } /** * Return a copy of the provided annotation with the specified point * added to the end of the point list. * @param annotation The annotation to update * @param position The position of the new point * @returns Updated copy of the annotation with the new point */ function appendPoint(annotation, position) { return { ...annotation, points: [...annotation.points, position] }; } /** * Return a copy of the provided annotation (or s-curve) with the specified color. * @param annotation The annotation to update * @param color The new color * @returns Updated copy of the annotation with the new color */ function changeColor(annotation, color) { return { ...annotation, color }; } /** * Return a copy of the provided annotation (or s-curve) with a new id, and optionally * any other fields provided. * @param annotation The annotation (or s-curve) to clone * @param changes Any other fields to update * @returns Clone of the annotation with new id (and any other updates) */ function clone(annotation, changes = {}) { return { ...annotation, ...changes, id: (0,uuid__WEBPACK_IMPORTED_MODULE_2__["default"])() }; } /** * Return a copy of the provided annotation (or s-curve) with hidden set to `true`. * @param annotation The annotation (or s-curve) to update * @returns The hidden copy of the annotation */ function hide(annotation) { return { ...annotation, hidden: true }; } /** * Return a copy of the provided annotation moved to the specified position. * @param annotation The annotation to update * @param position The new position * @returns Updated copy of the annotation with the new position */ function move(annotation, position) { return { ...annotation, position }; } /** * Return a copy of the provided annotation with the specified point moved * to the specified position. * @param annotation The annotation to update * @param pointIndex The point to update * @param position The new position * @returns Updated copy of the annotation with the new point position */ function movePoint(annotation, pointIndex, position) { return { ...annotation, points: annotation.points.toSpliced(pointIndex, 1, position) }; } /** * Return a copy of the provided annotation with the points replaced * with the specified points * @param annotation The annotation to update * @param points The new points * @returns Updated copy of the annotation with the new points */ function setPoints(annotation, points) { return { ...annotation, points }; } /** * Return a copy of the provided annotation with the specified point * added to the beginning of the point list. * @param annotation The annotation to update * @param position The position of the new point * @returns Updated copy of the annotation with the new point */ function prependPoint(annotation, position) { return { ...annotation, points: [position, ...annotation.points] }; } /** * Return a copy of the provided annotation (or s-curve) with the specified name. * @param annotation The annotation (or s-curve) to update * @param name The new name * @returns Updated copy of the annotation with the new name */ function rename(annotation, name) { return { ...annotation, name }; } /** * Return a copy of the provided annotation with the specified placeholderId * @param annotation The annotation to update * @param placeholderId The new placeholderId * @returns Updated copy of the annotation with the new placeholderId */ function setPlaceholderId(annotation, placeholderId) { return { ...annotation, placeholderId }; } /** * Return a copy of the provided annotation (or s-curve) with hidden set to `false`. * @param annotation The annotation (or s-curve) to update * @returns The visible copy of the annotation */ function show(annotation) { return { ...annotation, hidden: false }; } /** * Pre-multiply the Object3D's orientation by a rotation about a world-space axis. */ function rotateAboutAxis(annotation, axis, angleRad) { const normalizedAxis = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), axis); if (!Number.isFinite(normalizedAxis[0])) return annotation; // Axis–angle → unit quaternion: delta = (axis · sin(θ/2), cos(θ/2)). const delta = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), normalizedAxis, angleRad); // Axis is in world space, the new rotation in the world frame on top of the existing orientation,so: // right-drag updates compose in screen space ("stick with the cursor") rather than in the // object's local frame. Post-multiplying (current * delta) would rotate about the object's // own axes instead, which is not what a drag gesture wants. const next = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(next, delta, annotation.orientation); // Arrest floating-point drift because repeated multiplications slowly denormalize the quaternion, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(next, next); return { ...annotation, orientation: [next[0], next[1], next[2], next[3]] }; } /** * Toggle whether an Object3D is locked. A locked object cannot be translated or rotated. */ function toggleLock(annotation) { return { ...annotation, locked: !annotation.locked }; } /** Replace the Object3D's orientation quaternion. */ function setOrientation(annotation, orientation) { return { ...annotation, orientation }; } /** Reset the Object3D's orientation to identity (no rotation). */ function resetOrientation(annotation) { return { ...annotation, orientation: [0, 0, 0, 1] }; } /** Set the STL mesh's pivot (center of rotation). */ function setCenterOfRotation(annotation, centerOfRotation) { return { ...annotation, centerOfRotation }; } /** Replace the STL mesh's axis-of-symmetry rotation matrix (column-major, length 16). */ function setAxisOfSymmetryRotation(annotation, axisOfSymmetryRotation) { return { ...annotation, axisOfSymmetryRotation }; } /***/ }, /***/ 84249 /*!***********************************************!*\ !*** ./libs/domain/src/lib/updaters/index.ts ***! \***********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ addPointAt: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.addPointAt), /* harmony export */ appendPoint: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.appendPoint), /* harmony export */ changeColor: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.changeColor), /* harmony export */ clearAllPlaceholderAnnotations: () => (/* reexport safe */ _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__.clearAllPlaceholderAnnotations), /* harmony export */ clearPlaceholderAnnotations: () => (/* reexport safe */ _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__.clearPlaceholderAnnotations), /* harmony export */ clearProtocolFormValues: () => (/* reexport safe */ _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__.clearProtocolFormValues), /* harmony export */ clone: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.clone), /* harmony export */ hide: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.hide), /* harmony export */ move: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.move), /* harmony export */ movePoint: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.movePoint), /* harmony export */ prependPoint: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.prependPoint), /* harmony export */ removePointAt: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.removePointAt), /* harmony export */ rename: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.rename), /* harmony export */ resetOrientation: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.resetOrientation), /* harmony export */ rotateAboutAxis: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.rotateAboutAxis), /* harmony export */ setAxisOfSymmetryRotation: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.setAxisOfSymmetryRotation), /* harmony export */ setCenterOfRotation: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.setCenterOfRotation), /* harmony export */ setOrientation: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.setOrientation), /* harmony export */ setPlaceholderAnnotation: () => (/* reexport safe */ _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__.setPlaceholderAnnotation), /* harmony export */ setPlaceholderId: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.setPlaceholderId), /* harmony export */ setPoints: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.setPoints), /* harmony export */ setProtocolFormValues: () => (/* reexport safe */ _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__.setProtocolFormValues), /* harmony export */ show: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.show), /* harmony export */ toggleLock: () => (/* reexport safe */ _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__.toggleLock), /* harmony export */ updateRelativeMeasurement: () => (/* reexport safe */ _relative_measurements__WEBPACK_IMPORTED_MODULE_0__.updateRelativeMeasurement) /* harmony export */ }); /* harmony import */ var _relative_measurements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./relative-measurements */ 44216); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./annotation-updaters */ 77939); /* harmony import */ var _protocol_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./protocol-updaters */ 12300); /***/ }, /***/ 12300 /*!***********************************************************!*\ !*** ./libs/domain/src/lib/updaters/protocol-updaters.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ clearAllPlaceholderAnnotations: () => (/* binding */ clearAllPlaceholderAnnotations), /* harmony export */ clearPlaceholderAnnotations: () => (/* binding */ clearPlaceholderAnnotations), /* harmony export */ clearProtocolFormValues: () => (/* binding */ clearProtocolFormValues), /* harmony export */ setPlaceholderAnnotation: () => (/* binding */ setPlaceholderAnnotation), /* harmony export */ setProtocolFormValues: () => (/* binding */ setProtocolFormValues) /* harmony export */ }); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxdb */ 99984); function setPlaceholderAnnotation(instance, placeholderId, annotationId) { if (instance.placeholderMappings[placeholderId] === annotationId) { return instance; } return { ...instance, placeholderMappings: { ...instance.placeholderMappings, [placeholderId]: annotationId } }; } function clearPlaceholderAnnotations(instance, ...placeholderIds) { if (placeholderIds.length === 0) { return instance; } const newMappings = Object.fromEntries(Object.entries(instance.placeholderMappings).filter(([k]) => !placeholderIds.includes(k))); if ((0,rxdb__WEBPACK_IMPORTED_MODULE_0__.deepEqual)(instance.placeholderMappings, newMappings)) { return instance; } return { ...instance, placeholderMappings: newMappings }; } function clearAllPlaceholderAnnotations(instance) { if (Object.keys(instance.placeholderMappings).length === 0) { return instance; } return { ...instance, placeholderMappings: {} }; } function clearProtocolFormValues(instance) { if (instance.formValues === undefined) { return instance; } return { ...instance, formValues: undefined }; } function setProtocolFormValues(instance, formValues) { return { ...instance, formValues: { ...formValues } }; } /***/ }, /***/ 47686 /*!*****************************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/angle-between-spline-axes.ts ***! \*****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ angleBetweenSplineAxes: () => (/* binding */ angleBetweenSplineAxes) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../selectors/spline-selectors */ 28713); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../annotation-updaters */ 77939); function angleBetweenSplineAxes(annotation, sources) { const [spline1, spline2] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(spline1) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(spline2)) { console.warn('Missing or invalid parent inputs'); return annotation; } // Adapted from `AngleBetweenSplineAxesTool::bestAngleBetweenSplineAxes()` const [n1, n2] = [gl_matrix__WEBPACK_IMPORTED_MODULE_0__.clone((0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineBestFitNormal)(spline1)), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.clone((0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineBestFitNormal)(spline2))]; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n1, n1); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n2, n2); const n3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), n1, n2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n3, n3); const [p1, p2] = [(0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineCentroid)(spline1), (0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineCentroid)(spline2)]; // get point midway between two splines centers const p3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), p1, p2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(p3, p3, 0.5); // Projects p1 and p2 onto the plane defined by n3 const d1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), p1, p3); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(d1, p1, n3, -1 * gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(n3, d1)); const d2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), p2, p3); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(d2, p2, n3, -1 * gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(n3, d2)); // Calculate the point of intersection of the two lines // use fomula d1 + l*n1 where l = ±|n2 x (d2-d1)| / |n2 x n1| // d3 starts as d2 - d1 const d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), d2, d1); const n2xd3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), n2, d3); const n2xd3Length = Math.sqrt(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(n2xd3, n2xd3)); const n2xn1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), n2, n1); const n2xn1Length = Math.sqrt(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(n2xn1, n2xn1)); const l = n2xd3Length / n2xn1Length; // Calculate the point of intersection of the two lines and store in d3 gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(d3, d1, n1, l); // We need to ensure that sign of l is correct // Calculate the angle between the two lines segments d1-d3 and d2-d3 const d1d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), d1, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(d1d3, d1d3); const d2d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), d2, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(d2d3, d2d3); const angle1 = Math.acos(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(d1d3, d2d3)); // Calculate the angle between the two vectors n1 and n2 const angle2 = Math.acos(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(n1, n2)); // Ensure that the sign of `l` is correct by checking if the angle // between the two lines segments and the vectors is similar if (Math.abs(angle1 - angle2) % Math.PI > Math.PI / 180 || Math.abs(2 * Math.PI - angle1 + angle2) % Math.PI - Math.PI > Math.PI / 180) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(d3, d1, n1, -1 * l); } // Calculate distance between center point and both spline center midway point. if too far do not draw angle // and prevent go to const pMiddle = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), p1, p2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(pMiddle, pMiddle, 0.5); const vSplines = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), p2, p1); const vAngle = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), pMiddle, d3); // If failure conditions are present, return UNINIT points, // which will not be rendered. if (!isValidAngle(angle1, angle2, vAngle, vSplines)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_4__.setPoints)(annotation, [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.UNINIT]); } return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_4__.setPoints)(annotation, [(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.vec3ToPosition)(d1), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.vec3ToPosition)(d3), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.vec3ToPosition)(d2)]); } function isValidAngle(angle1, angle2, vAngle, vSplines) { const p3Distance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(vAngle); const splineDistance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(vSplines); if (Number.isNaN(angle1) || Number.isNaN(angle2)) { return false; } if (p3Distance > 2 * splineDistance) { return false; } return true; } /***/ }, /***/ 23077 /*!*************************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/angle-between-splines.ts ***! \*************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ angleBetweenSplines: () => (/* binding */ angleBetweenSplines) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 97339); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 93067); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../selectors/spline-selectors */ 28713); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../annotation-updaters */ 77939); function angleBetweenSplines(annotation, sources) { const [spline1, spline2] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsClosedSpline)(spline1) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsClosedSpline)(spline2)) { console.warn('Missing or invalid parent inputs'); return annotation; } // Adapted from `AngleBetweenSplinesTool::bestAngleBetweenSplineTools()` const [normal1, normal2] = [gl_matrix__WEBPACK_IMPORTED_MODULE_2__.clone((0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineBestFitNormal)(spline1)), gl_matrix__WEBPACK_IMPORTED_MODULE_2__.clone((0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineBestFitNormal)(spline2))]; gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(normal1, normal1); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(normal2, normal2); const normal3 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), normal1, normal2); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(normal3, normal3); const [centroid1, centroid2] = [(0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineCentroid)(spline1), (0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineCentroid)(spline2)]; const index = normal3.map(number_ => Math.abs(number_)).indexOf(Math.max(...normal3)); const a = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); if (index === 3) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(a, normal1[0], normal2[0], normal1[1], normal2[1]); } else if (index === 2) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(a, normal1[0], normal2[0], normal1[2], normal2[2]); } else { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(a, normal1[1], normal2[1], normal1[2], normal2[2]); } const b = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal1, centroid1), gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal2, centroid2)); const invA = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.invert(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), a); if (invA === null) { console.warn("can't invert!"); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(invA, a[0], a[1], a[2], a[3]); } const p = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat2(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), b, invA); const p3 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(); if (index === 3) { gl_matrix__WEBPACK_IMPORTED_MODULE_2__.set(p3, p[0], p[1], 0); } else if (index === 2) { gl_matrix__WEBPACK_IMPORTED_MODULE_2__.set(p3, p[0], 0, p[1]); } else { gl_matrix__WEBPACK_IMPORTED_MODULE_2__.set(p3, 0, p[0], p[1]); } const d1 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), centroid1, p3); const l1 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal3, d1); const d2 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), centroid2, p3); const l2 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal3, d2); const d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scaleAndAdd(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), p3, normal3, (l1 + l2) * 0.5); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(d1, centroid1, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scaleAndAdd(d1, centroid1, normal3, -1 * gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal3, d1)); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(d2, centroid2, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scaleAndAdd(d2, centroid2, normal3, -1 * gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal3, d2)); const [perimeter1, perimeter2] = [(0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineLength)(spline1), (0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineLength)(spline2)]; const r1 = perimeter1 / 2 / Math.PI; gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(normal1, d1, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(normal1, normal1); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scaleAndAdd(d1, d1, normal1, r1); const r2 = perimeter2 / 2 / Math.PI; gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(normal2, d2, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(normal2, normal2); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scaleAndAdd(d2, d2, normal2, r2); // If failure conditions are present, return UNINIT points, // which will not be rendered. if (!isValidAngle(normal1, normal2, centroid1, centroid2, d1, d2, d3)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_6__.setPoints)(annotation, [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.UNINIT, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.UNINIT]); } return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_6__.setPoints)(annotation, [(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.vec3ToPosition)(d1), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.vec3ToPosition)(d3), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.vec3ToPosition)(d2)]); } function isValidAngle(normal1, normal2, centroid1, centroid2, d1, d2, d3) { const angle1 = Math.acos(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(normal1, normal2)); if (Number.isNaN(angle1)) { return false; } // Calculate the angle between the two lines segments d1-d3 and d2-d3 const d1d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), d1, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(d1d3, d1d3); const d2d3 = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), d2, d3); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(d2d3, d2d3); const angle2 = Math.acos(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.dot(d1d3, d2d3)); if (Number.isNaN(angle2)) { return false; } // Calculate distance between center point and both spline center midway points. // Ensure it is not too far eg. a very small angle const pMiddle = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), centroid1, centroid2); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.scale(pMiddle, pMiddle, 0.5); const vSplines = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), centroid2, centroid1); const vAngle = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), pMiddle, d3); const p3Distance = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.length(vAngle); const splineDistance = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.length(vSplines); return p3Distance <= 2 * splineDistance; } /***/ }, /***/ 24076 /*!*********************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/attached-distance.ts ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ attachedDistance: () => (/* binding */ attachedDistance) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils */ 87653); /** * Updates the provided Distance so that the first point still sits within the * source annotation's path. * * @param annotation The Distance annotation to be updated * @param sources The parent which the Distance is bound to */ function attachedDistance(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start] = annotation.points; if (!start) { return annotation; } const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(start, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, start)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.movePoint)(annotation, 0, snapped); } return annotation; } /***/ }, /***/ 47041 /*!******************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/attached-point.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ attachedPoint: () => (/* binding */ attachedPoint) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils */ 87653); /** * Updates the provided Point so that it sits within the * source annotation's path. * * @param annotation The Point annotation to be updated * @param sources The parent which the Point is bound to */ function attachedPoint(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(annotation.position, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, annotation.position)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.move)(annotation, snapped); } return annotation; } /***/ }, /***/ 78670 /*!*******************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/attached-spline.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ attachedSpline: () => (/* binding */ attachedSpline) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ 87653); /** * Updates the provided Spline so that the first point still sits within the * source annotation's path. * * @param annotation The Spline annotation to be updated * @param sources The parent which the Spline is bound to */ function attachedSpline(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start, ...rest] = annotation.points; if (!start) { console.warn('Expected points on distance!'); return annotation; } const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.snapToAnnotation)(start, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, start)) { return { ...annotation, points: [snapped, ...rest] }; } return annotation; } /***/ }, /***/ 65743 /*!*******************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/center-distance.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ centerDistance: () => (/* binding */ centerDistance) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../selectors/annotation-selectors */ 66817); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../annotation-updaters */ 77939); function centerDistance(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start] = annotation.points; if (!start) { return annotation; } const centroid = (0,_selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(centroid, start)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_3__.movePoint)(annotation, 0, centroid); } return annotation; } /***/ }, /***/ 45298 /*!*********************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/chord.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ chord: () => (/* binding */ chord) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils */ 87653); /** * Updates the provided Distance so that the points sit within the * source annotation's path. * * @param annotation The Distance annotation to be updated * @param sources The parent which the Distance is bound to */ function chord(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start, end] = annotation.points; if (!start) { return annotation; } if (!end) { // Only update the first point const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(start, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, start)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.movePoint)(annotation, 0, snapped); } return annotation; } const [snappedStart, snappedEnd] = [(0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(start, source), (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(end, source)]; if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snappedStart, start) || !(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snappedEnd, end)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.setPoints)(annotation, [snappedStart, snappedEnd]); } return annotation; } /***/ }, /***/ 14057 /*!****************************************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/closest-distance-between-annotations.ts ***! \****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestDistanceBetweenAnnotations: () => (/* binding */ closestDistanceBetweenAnnotations) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../selectors/annotation-selectors */ 66817); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /** * Updates the provided Distance so that the points sit within the paths * of each source annotation, at the positions closest to each other. * * @param annotation The Distance annotation to be updated * @param sources The parents which the Distance is bound to */ function closestDistanceBetweenAnnotations(annotation, sources) { const [from, to] = sources; if (!from || !to) { console.warn('Missing or invalid parent inputs'); return annotation; } const fromPath = (0,_selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_1__.getPath)(from); const toPath = (0,_selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_1__.getPath)(to); return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.setPoints)(annotation, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.closestPointsBetweenPaths)(fromPath, toPath)); } /***/ }, /***/ 38892 /*!**************************************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/closest-distance-to-one-annotation.ts ***! \**************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestDistanceToOneAnnotation: () => (/* binding */ closestDistanceToOneAnnotation) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils */ 87653); /** * Updates the provided Distance so that the first point still sits within the * source annotation's path, based on the closest point to the end point. * * @param annotation The Distance annotation to be updated * @param sources The parent which the Distance is bound to */ function closestDistanceToOneAnnotation(annotation, sources) { const [source] = sources; if (!source || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start, end] = annotation.points; if (start === undefined) { return annotation; } if (end === undefined) { // No end point, treat the first point the same as in attached distance const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(start, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, start)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.movePoint)(annotation, 0, snapped); } } else { const snapped = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.snapToAnnotation)(end, source); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.positionsEqual)(snapped, start)) { return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_2__.movePoint)(annotation, 0, snapped); } } return annotation; } /***/ }, /***/ 76076 /*!********************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/distance-between.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ distanceBetween: () => (/* binding */ distanceBetween) /* harmony export */ }); /* harmony import */ var _selectors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../selectors */ 27531); /** * Updates the provided Distance so the two points represent the positions * of the parent annotations' centroids. * NOTE: This is more an example - I don't believe the educational version * has this exact relative measurement. * @param annotation The Distance annotation to be updated * @param sources The two parents representing the point of the distance * @returns Updated version of the Distance */ function distanceBetween(annotation, sources) { const [start, end] = sources; if (!start || !end) { console.warn('Missing or invalid parent inputs'); return annotation; } return { ...annotation, points: [(0,_selectors__WEBPACK_IMPORTED_MODULE_0__.getCentroid)(start), (0,_selectors__WEBPACK_IMPORTED_MODULE_0__.getCentroid)(end)] }; } /***/ }, /***/ 44216 /*!*********************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/index.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ updateRelativeMeasurement: () => (/* binding */ updateRelativeMeasurement) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _angle_between_spline_axes__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./angle-between-spline-axes */ 47686); /* harmony import */ var _angle_between_splines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./angle-between-splines */ 23077); /* harmony import */ var _attached_distance__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./attached-distance */ 24076); /* harmony import */ var _attached_point__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./attached-point */ 47041); /* harmony import */ var _attached_spline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./attached-spline */ 78670); /* harmony import */ var _center_distance__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./center-distance */ 65743); /* harmony import */ var _chord__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./chord */ 45298); /* harmony import */ var _closest_distance_between_annotations__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./closest-distance-between-annotations */ 14057); /* harmony import */ var _closest_distance_to_one_annotation__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./closest-distance-to-one-annotation */ 38892); /* harmony import */ var _distance_between__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./distance-between */ 76076); /* harmony import */ var _projected_distance__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./projected-distance */ 54542); /* harmony import */ var _projected_distance_from_point__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./projected-distance-from-point */ 44728); const MEASUREMENT_LOOKUP = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE]: { 'angle-between-spline-axes': _angle_between_spline_axes__WEBPACK_IMPORTED_MODULE_2__.angleBetweenSplineAxes, 'angle-between-splines': _angle_between_splines__WEBPACK_IMPORTED_MODULE_3__.angleBetweenSplines }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE]: {}, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CYLINDER]: {}, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE]: { 'attached-distance': _attached_distance__WEBPACK_IMPORTED_MODULE_4__.attachedDistance, 'center-distance': _center_distance__WEBPACK_IMPORTED_MODULE_7__.centerDistance, chord: _chord__WEBPACK_IMPORTED_MODULE_8__.chord, 'closest-distance-between-annotations': _closest_distance_between_annotations__WEBPACK_IMPORTED_MODULE_9__.closestDistanceBetweenAnnotations, 'closest-distance-to-one-annotation': _closest_distance_to_one_annotation__WEBPACK_IMPORTED_MODULE_10__.closestDistanceToOneAnnotation, 'distance-between': _distance_between__WEBPACK_IMPORTED_MODULE_11__.distanceBetween, 'projected-distance': _projected_distance__WEBPACK_IMPORTED_MODULE_12__.projectedDistance, 'projected-distance-from-point': _projected_distance_from_point__WEBPACK_IMPORTED_MODULE_13__.projectedDistanceFromPoint }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.HOLLOW_CYLINDER]: {}, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE]: { 'attached-spline': _attached_spline__WEBPACK_IMPORTED_MODULE_6__.attachedSpline }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT]: { 'attached-point': _attached_point__WEBPACK_IMPORTED_MODULE_5__.attachedPoint, 'curvature-point': _attached_point__WEBPACK_IMPORTED_MODULE_5__.attachedPoint }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.STL]: {} }; /** * Apply the proper relative measurement updater to the provided annotation, * based on the state of its sources. * If no updater exists for the specified relationship, no changes will be made. * @param annotation The relative measurement annotation to update * @param sources The source annotations to derive the updates from * @returns A copy of the provided annotation, with updates based on the relative measurement type. */ function updateRelativeMeasurement(annotation, sources) { if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationHasRelationship)(annotation)) { return annotation; } const updater = MEASUREMENT_LOOKUP[annotation.type]?.[annotation.relationship.type]; return updater?.(annotation, sources) ?? annotation; } /***/ }, /***/ 44728 /*!*********************************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/projected-distance-from-point.ts ***! \*********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectedDistanceFromPoint: () => (/* binding */ projectedDistanceFromPoint) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../selectors/annotation-selectors */ 66817); /* harmony import */ var _selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../selectors/spline-selectors */ 28713); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /** * Updates the provided Distance so that the first point is always perpendicular * to the second point (which is always at the source point's position), and on the source spline's plane. */ function projectedDistanceFromPoint(annotation, sources) { const [spline, point] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsSpline)(spline) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsPoint)(point)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start, end] = annotation.points; if (start === undefined || end === undefined) { return annotation; } const newPoint = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.projectPointOnPlane)(point.position, (0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineBestFitNormal)(spline), (0,_selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(spline)); return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_4__.setPoints)(annotation, [(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(newPoint), [...point.position]]); } /***/ }, /***/ 54542 /*!**********************************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/projected-distance.ts ***! \**********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectedDistance: () => (/* binding */ projectedDistance) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../selectors/annotation-selectors */ 66817); /* harmony import */ var _selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../selectors/spline-selectors */ 28713); /* harmony import */ var _annotation_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../annotation-updaters */ 77939); /** * Updates the provided Distance so that the first point is always perpendicular * to the second point, and on the source annotation's plane. */ function projectedDistance(annotation, sources) { const [source] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsSpline)(source)) { console.warn('Missing or invalid parent inputs'); return annotation; } const [start, end] = annotation.points; if (start === undefined || end === undefined) { return annotation; } const newPoint = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.projectPointOnPlane)(end, (0,_selectors_spline_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplineBestFitNormal)(source), (0,_selectors_annotation_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(source)); return (0,_annotation_updaters__WEBPACK_IMPORTED_MODULE_4__.movePoint)(annotation, 0, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(newPoint)); } /***/ }, /***/ 87653 /*!*********************************************************************!*\ !*** ./libs/domain/src/lib/updaters/relative-measurements/utils.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ snapToAnnotation: () => (/* binding */ snapToAnnotation) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../selectors */ 27531); /* eslint-disable sonarjs/cyclomatic-complexity */ /** * Given a position and a annotation, return the position on the annotation's path * that is closest to the original position. * @param position The position to snap * @param annotation The annotation to snap onto * @returns A position on the annotation's path that is closest to the original position. */ function snapToAnnotation(position, annotation) { if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT) { return annotation.position; } if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE) { const [start, end] = annotation.points; if (start === undefined || end === undefined) { console.warn('Distance annotation missing points'); return position; } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.snapPositionToLine)(position, start, end); } if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE) { const [start, middle, end] = annotation.points; if (start === undefined || middle === undefined || end === undefined) { console.warn('Angle annotation missing points'); return position; } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.snapPositionToAngle)(position, start, middle, end); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsSpline)(annotation)) { const path = (0,_selectors__WEBPACK_IMPORTED_MODULE_3__.getSplinePath)(annotation); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.snapPositionToSpline)(position, path); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsObject3D)(annotation)) { return (0,_selectors__WEBPACK_IMPORTED_MODULE_3__.snapPositionToObject3D)(position, (0,_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DGeometry)(annotation), (0,_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DTransformMatrix)(annotation), (0,_selectors__WEBPACK_IMPORTED_MODULE_3__.getObject3DOctree)(annotation)); } return position; } /***/ }, /***/ 74208 /*!*************************************************!*\ !*** ./libs/domain/src/lib/validators/index.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ validateProtocolForm: () => (/* reexport safe */ _protocol_form_validators__WEBPACK_IMPORTED_MODULE_0__.validateProtocolForm), /* harmony export */ validateProtocolFormField: () => (/* reexport safe */ _protocol_form_validators__WEBPACK_IMPORTED_MODULE_0__.validateProtocolFormField) /* harmony export */ }); /* harmony import */ var _protocol_form_validators__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./protocol-form-validators */ 75617); /***/ }, /***/ 75617 /*!********************************************************************!*\ !*** ./libs/domain/src/lib/validators/protocol-form-validators.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ validateProtocolForm: () => (/* binding */ validateProtocolForm), /* harmony export */ validateProtocolFormField: () => (/* binding */ validateProtocolFormField) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); function validateProtocolForm(rules, values) { const result = { errors: {}, valid: true }; for (const [key, rule] of Object.entries(rules)) { const result_ = validateProtocolFormField(rule, key, values); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isFail)(result_)) { result.valid = false; result.errors[key] = result_.error ?? 'This field is invalid.'; } } return result; } // eslint-disable-next-line sonarjs/cyclomatic-complexity,sonarjs/cognitive-complexity function validateProtocolFormField(rule, field, values) { switch (rule.type) { case 'and': { for (const rule_ of rule.rules) { const result = validateProtocolFormField(rule_, field, values); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isFail)(result)) { return result; } } return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.pass)(); } case 'equals': { const value = values[field]; return value === rule.value ? (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.pass)() : (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.fail)(rule.message ?? `Expected ${field} to equal ${rule.value}`); } case 'for-field': { return validateProtocolFormField(rule.rule, rule.field, values); } case 'if': { const condition = validateProtocolFormField(rule.condition, field, values); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isPass)(condition)) { return validateProtocolFormField(rule.rule, field, values); } else if (rule.elseRule === undefined) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.skip)(); } else { return validateProtocolFormField(rule.elseRule, field, values); } } case 'one-of': { const value = values[field]; if (Array.isArray(value) || value === undefined) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.fail)('Validation rule not supported for array type'); } return rule.values.includes(value) ? (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.pass)() : (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.fail)(rule.message ?? `Expected ${field} to be one of: ${rule.values.join(',')}`); } case 'or': { const results = rule.rules.map(rule_ => validateProtocolFormField(rule_, field, values)); if (results.some(result => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isPass)(result))) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.pass)(); } const errors = results.map(rule_ => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isFail)(rule_) ? rule_.error : undefined).filter(error => error != undefined); return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.fail)(`One of the following conditions should be true:\n${errors.join('\n')}`); } case 'required': { const value = values[field]; if (typeof value === 'string' && value.trim().length === 0 || Array.isArray(value) && value.length === 0 || value === undefined) { return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.fail)(rule.message ?? 'This field is required.'); } return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.pass)(); } } } /***/ }, /***/ 8938 /*!***********************************!*\ !*** ./libs/feature/src/index.ts ***! \***********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationActorsService: () => (/* reexport safe */ _lib_volume_viewer_annotation_actors_annotation_actors_service__WEBPACK_IMPORTED_MODULE_15__.AnnotationActorsService), /* harmony export */ AnnotationCardComponent: () => (/* reexport safe */ _lib_annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_18__.AnnotationCardComponent), /* harmony export */ AnnotationExportBridge: () => (/* reexport safe */ _lib_dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_34__.AnnotationExportBridge), /* harmony export */ AnnotationMenuComponent: () => (/* reexport safe */ _lib_annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_25__.AnnotationMenuComponent), /* harmony export */ AnnotationMenuItemComponent: () => (/* reexport safe */ _lib_annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_26__.AnnotationMenuItemComponent), /* harmony export */ AnnotationMenuItemService: () => (/* reexport safe */ _lib_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_24__.AnnotationMenuItemService), /* harmony export */ AnnotationMenuTriggerDirective: () => (/* reexport safe */ _lib_annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_27__.AnnotationMenuTriggerDirective), /* harmony export */ AnnotationPanelComponent: () => (/* reexport safe */ _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__.AnnotationPanelComponent), /* harmony export */ COLORS_TOKEN: () => (/* reexport safe */ _lib_colors_colors_config__WEBPACK_IMPORTED_MODULE_20__.COLORS_TOKEN), /* harmony export */ CameraSliderComponent: () => (/* reexport safe */ _lib_dual_axis_slider_camera_slider_component__WEBPACK_IMPORTED_MODULE_23__.CameraSliderComponent), /* harmony export */ ChamberCardComponent: () => (/* reexport safe */ _lib_chamber_chamber_card_chamber_card_component__WEBPACK_IMPORTED_MODULE_37__.ChamberCardComponent), /* harmony export */ ChamberMenuComponent: () => (/* reexport safe */ _lib_chamber_chamber_menu_components_chamber_menu_component__WEBPACK_IMPORTED_MODULE_40__.ChamberMenuComponent), /* harmony export */ ChamberMenuItemComponent: () => (/* reexport safe */ _lib_chamber_chamber_menu_components_chamber_menu_item_component__WEBPACK_IMPORTED_MODULE_41__.ChamberMenuItemComponent), /* harmony export */ ChamberMenuItemService: () => (/* reexport safe */ _lib_chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_38__.ChamberMenuItemService), /* harmony export */ ChamberMenuTriggerDirective: () => (/* reexport safe */ _lib_chamber_chamber_menu_directives_chamber_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_42__.ChamberMenuTriggerDirective), /* harmony export */ ChamberPanelComponent: () => (/* reexport safe */ _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__.ChamberPanelComponent), /* harmony export */ ChamberService: () => (/* reexport safe */ _lib_chamber_chamber_service__WEBPACK_IMPORTED_MODULE_39__.ChamberService), /* harmony export */ ColorsService: () => (/* reexport safe */ _lib_colors_colors_service__WEBPACK_IMPORTED_MODULE_19__.ColorsService), /* harmony export */ DeviceSizingChartDialogComponent: () => (/* reexport safe */ _lib_device_sizing_chart_device_sizing_chart_dialog_component__WEBPACK_IMPORTED_MODULE_16__.DeviceSizingChartDialogComponent), /* harmony export */ DeviceSizingChartDialogService: () => (/* reexport safe */ _lib_device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_17__.DeviceSizingChartDialogService), /* harmony export */ FULL_PICKER_COLORS_TOKEN: () => (/* reexport safe */ _lib_colors_colors_config__WEBPACK_IMPORTED_MODULE_20__.FULL_PICKER_COLORS_TOKEN), /* harmony export */ ImagingLibraryPageComponent: () => (/* reexport safe */ _lib_imaging_library_imaging_library_page_component__WEBPACK_IMPORTED_MODULE_2__.ImagingLibraryPageComponent), /* harmony export */ LiveAnalysesPageComponent: () => (/* reexport safe */ _lib_imaging_library_live_analyses_page_component__WEBPACK_IMPORTED_MODULE_3__.LiveAnalysesPageComponent), /* harmony export */ LoggingService: () => (/* reexport safe */ _lib_logging_logging_service__WEBPACK_IMPORTED_MODULE_30__.LoggingService), /* harmony export */ MPR_VIEWPORT_ID_LIST: () => (/* reexport safe */ _lib_volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_14__.MPR_VIEWPORT_ID_LIST), /* harmony export */ ModalityLabelPipe: () => (/* reexport safe */ _lib_pipes_modality_label_pipe__WEBPACK_IMPORTED_MODULE_29__.ModalityLabelPipe), /* harmony export */ NON_DEGRADING_VIEWPORT_ID_LIST: () => (/* reexport safe */ _lib_volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_14__.NON_DEGRADING_VIEWPORT_ID_LIST), /* harmony export */ PICKER_COLORS_TOKEN: () => (/* reexport safe */ _lib_colors_colors_config__WEBPACK_IMPORTED_MODULE_20__.PICKER_COLORS_TOKEN), /* harmony export */ PlanarReformationPanelComponent: () => (/* reexport safe */ _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__.PlanarReformationPanelComponent), /* harmony export */ ProtocolPanelComponent: () => (/* reexport safe */ _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__.ProtocolPanelComponent), /* harmony export */ SCurveCardComponent: () => (/* reexport safe */ _lib_s_curve_card_s_curve_card_component__WEBPACK_IMPORTED_MODULE_21__.SCurveCardComponent), /* harmony export */ SCurveGraphPopoverService: () => (/* reexport safe */ _lib_volume_viewer_s_curve_graph_popover_service__WEBPACK_IMPORTED_MODULE_11__.SCurveGraphPopoverService), /* harmony export */ SCurvePanelComponent: () => (/* reexport safe */ _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__.SCurvePanelComponent), /* harmony export */ SubmenuFlipService: () => (/* reexport safe */ _lib_services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_43__.SubmenuFlipService), /* harmony export */ TAVI_PROTOCOL_ID: () => (/* reexport safe */ _lib_dicom_importer_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_35__.TAVI_PROTOCOL_ID), /* harmony export */ TaviProtocol: () => (/* reexport safe */ _lib_protocols_definitions_tavi_protocol__WEBPACK_IMPORTED_MODULE_33__.TaviProtocol), /* harmony export */ ThemePreviewPageComponent: () => (/* reexport safe */ _lib_theme_preview_theme_preview_page_component__WEBPACK_IMPORTED_MODULE_4__.ThemePreviewPageComponent), /* harmony export */ ToolMenuComponent: () => (/* reexport safe */ _lib_tool_menu_tool_menu_component__WEBPACK_IMPORTED_MODULE_22__.ToolMenuComponent), /* harmony export */ TopNavigationComponent: () => (/* reexport safe */ _lib_top_navigation_top_navigation_component__WEBPACK_IMPORTED_MODULE_1__.TopNavigationComponent), /* harmony export */ VIEWPORT_IDS: () => (/* reexport safe */ _lib_volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_14__.VIEWPORT_IDS), /* harmony export */ VOLUME_VIEWER_OPTIONS: () => (/* reexport safe */ _lib_volume_viewer_provide_volume_viewer__WEBPACK_IMPORTED_MODULE_12__.VOLUME_VIEWER_OPTIONS), /* harmony export */ VolumeViewerComponent: () => (/* reexport safe */ _lib_volume_viewer_volume_viewer_component__WEBPACK_IMPORTED_MODULE_9__.VolumeViewerComponent), /* harmony export */ VolumeViewerOrchestrator: () => (/* reexport safe */ _lib_volume_viewer_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_10__.VolumeViewerOrchestrator), /* harmony export */ WindowService: () => (/* reexport safe */ _lib_window_window_service__WEBPACK_IMPORTED_MODULE_28__.WindowService), /* harmony export */ WorkSessionDialogService: () => (/* reexport safe */ _lib_work_session_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_7__.WorkSessionDialogService), /* harmony export */ WorkSessionImportService: () => (/* reexport safe */ _lib_work_session_work_session_import_service__WEBPACK_IMPORTED_MODULE_6__.WorkSessionImportService), /* harmony export */ WorkSessionService: () => (/* reexport safe */ _lib_work_session_work_session_service__WEBPACK_IMPORTED_MODULE_5__.WorkSessionService), /* harmony export */ WorkSessionSwitchService: () => (/* reexport safe */ _lib_work_session_work_session_switch_service__WEBPACK_IMPORTED_MODULE_8__.WorkSessionSwitchService), /* harmony export */ buildProtocolBindings: () => (/* reexport safe */ _lib_dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_34__.buildProtocolBindings), /* harmony export */ deserializeAnnotationPayload: () => (/* reexport safe */ _lib_dicom_importer_services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_36__.deserializeAnnotationPayload), /* harmony export */ extractAnnotationTags: () => (/* reexport safe */ _lib_dicom_importer_services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_36__.extractAnnotationTags), /* harmony export */ getLogger: () => (/* reexport safe */ _lib_logging_utils__WEBPACK_IMPORTED_MODULE_31__.getLogger), /* harmony export */ mapViewportNameToId: () => (/* reexport safe */ _lib_volume_viewer_map_viewport_name_to_id__WEBPACK_IMPORTED_MODULE_13__.mapViewportNameToId), /* harmony export */ oauthPageRoutes: () => (/* reexport safe */ _lib_oauth_feature_pages_oauth_page_routes__WEBPACK_IMPORTED_MODULE_0__.oauthPageRoutes), /* harmony export */ provideDefaultColors: () => (/* reexport safe */ _lib_colors_colors_config__WEBPACK_IMPORTED_MODULE_20__.provideDefaultColors), /* harmony export */ provideVolumeViewer: () => (/* reexport safe */ _lib_volume_viewer_provide_volume_viewer__WEBPACK_IMPORTED_MODULE_12__.provideVolumeViewer), /* harmony export */ rebuildProtocolState: () => (/* reexport safe */ _lib_dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_34__.rebuildProtocolState) /* harmony export */ }); /* harmony import */ var _lib_oauth_feature_pages_oauth_page_routes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/oauth-feature-pages/oauth-page.routes */ 40531); /* harmony import */ var _lib_top_navigation_top_navigation_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/top-navigation/top-navigation.component */ 71202); /* harmony import */ var _lib_imaging_library_imaging_library_page_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/imaging-library/imaging-library-page.component */ 96472); /* harmony import */ var _lib_imaging_library_live_analyses_page_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/imaging-library/live-analyses-page.component */ 99957); /* harmony import */ var _lib_theme_preview_theme_preview_page_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/theme-preview/theme-preview-page.component */ 79428); /* harmony import */ var _lib_work_session_work_session_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/work-session/work-session.service */ 82757); /* harmony import */ var _lib_work_session_work_session_import_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/work-session/work-session-import.service */ 50784); /* harmony import */ var _lib_work_session_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/work-session/work-session-dialog.service */ 35009); /* harmony import */ var _lib_work_session_work_session_switch_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/work-session/work-session-switch.service */ 5497); /* harmony import */ var _lib_volume_viewer_volume_viewer_component__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/volume-viewer/volume-viewer.component */ 28828); /* harmony import */ var _lib_volume_viewer_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/volume-viewer/volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _lib_volume_viewer_s_curve_graph_popover_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/volume-viewer/s-curve-graph-popover.service */ 57669); /* harmony import */ var _lib_volume_viewer_provide_volume_viewer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./lib/volume-viewer/provide-volume-viewer */ 21321); /* harmony import */ var _lib_volume_viewer_map_viewport_name_to_id__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./lib/volume-viewer/map-viewport-name-to-id */ 77335); /* harmony import */ var _lib_volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/volume-viewer/viewport-ids */ 85309); /* harmony import */ var _lib_volume_viewer_annotation_actors_annotation_actors_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./lib/volume-viewer/annotation-actors/annotation-actors.service */ 12100); /* harmony import */ var _lib_device_sizing_chart_device_sizing_chart_dialog_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./lib/device-sizing-chart/device-sizing-chart-dialog.component */ 20619); /* harmony import */ var _lib_device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./lib/device-sizing-chart/device-sizing-chart-dialog.service */ 26755); /* harmony import */ var _lib_annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./lib/annotation-card/annotation-card.component */ 86628); /* harmony import */ var _lib_colors_colors_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./lib/colors/colors.service */ 39298); /* harmony import */ var _lib_colors_colors_config__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./lib/colors/colors.config */ 98063); /* harmony import */ var _lib_s_curve_card_s_curve_card_component__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./lib/s-curve-card/s-curve-card.component */ 31982); /* harmony import */ var _lib_tool_menu_tool_menu_component__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./lib/tool-menu/tool-menu.component */ 75048); /* harmony import */ var _lib_dual_axis_slider_camera_slider_component__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./lib/dual-axis-slider/camera-slider.component */ 66039); /* harmony import */ var _lib_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./lib/annotation-menu/annotation-menu-item.service */ 39860); /* harmony import */ var _lib_annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./lib/annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _lib_annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./lib/annotation-menu/components/annotation-menu-item.component */ 45731); /* harmony import */ var _lib_annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./lib/annotation-menu/directives/annotation-menu-trigger.directive */ 12564); /* harmony import */ var _lib_window_window_service__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./lib/window/window.service */ 26914); /* harmony import */ var _lib_pipes_modality_label_pipe__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./lib/pipes/modality-label.pipe */ 18194); /* harmony import */ var _lib_logging_logging_service__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./lib/logging/logging.service */ 47136); /* harmony import */ var _lib_logging_utils__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./lib/logging/utils */ 14337); /* harmony import */ var _lib_sidebar_panels__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./lib/sidebar-panels */ 77391); /* harmony import */ var _lib_protocols_definitions_tavi_protocol__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./lib/protocols/definitions/tavi.protocol */ 12541); /* harmony import */ var _lib_dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./lib/dicom-importer/services/annotation-export-bridge.service */ 68674); /* harmony import */ var _lib_dicom_importer_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./lib/dicom-importer/services/dicom-export.service */ 8027); /* harmony import */ var _lib_dicom_importer_services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./lib/dicom-importer/services/dicom-annotation-codec */ 19462); /* harmony import */ var _lib_chamber_chamber_card_chamber_card_component__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./lib/chamber/chamber-card/chamber-card.component */ 69605); /* harmony import */ var _lib_chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./lib/chamber/chamber-menu/chamber-menu-item.service */ 44189); /* harmony import */ var _lib_chamber_chamber_service__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./lib/chamber/chamber.service */ 16592); /* harmony import */ var _lib_chamber_chamber_menu_components_chamber_menu_component__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./lib/chamber/chamber-menu/components/chamber-menu.component */ 23204); /* harmony import */ var _lib_chamber_chamber_menu_components_chamber_menu_item_component__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./lib/chamber/chamber-menu/components/chamber-menu-item.component */ 11612); /* harmony import */ var _lib_chamber_chamber_menu_directives_chamber_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./lib/chamber/chamber-menu/directives/chamber-menu-trigger.directive */ 65937); /* harmony import */ var _lib_services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./lib/services/submenu-flip/submenu-flip.service */ 9610); // Oauth router // Top Navigation // Imaging Library // Theme preview (dev-only route) // Work Session // Volume Viewer // Device Sizing Chart // Tool Menu // Orbital Camera // Annotation Menu // Pipes // Logging // Sidebar Panels // DICOM Export // Chamber Card // Services /***/ }, /***/ 86628 /*!***************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-card/annotation-card.component.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationCardComponent: () => (/* binding */ AnnotationCardComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../annotation-menu/directives/annotation-menu-trigger.directive */ 12564); /* harmony import */ var _card_theme_card_interaction__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../card-theme/card-interaction */ 35946); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../card-theme/card-theme */ 92147); const _c0 = ["nameInput"]; const _c1 = ["nameLabel"]; const _c2 = ["suggestionsPopover"]; const _c3 = ["suggestionButton"]; const _c4 = () => ({ root: "size-6 shrink-0" }); const _c5 = () => ({ root: "py-1 px-0" }); const _c6 = () => ({ color: "var(--p-accordion-header-toggle-icon-color)" }); const _c7 = a0 => ({ secondary: a0 }); const _c8 = a0 => ({ outlined: a0 }); const _forTrack0 = ($index, $item) => $item.name; const _forTrack1 = ($index, $item) => $item.icon; function AnnotationCardComponent_ng_container_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_Conditional_5_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](0, AnnotationCardComponent_Conditional_5_ng_container_0_Template, 1, 0, "ng-container", 18); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const dragHandle_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", dragHandle_r2); } } function AnnotationCardComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 23); } if (rf & 2) { const active_r3 = ctx.active; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("p-accordionheader-toggle-icon size-(--p-app-icon-size-xxxs) text-(length:--p-app-icon-size-xxxs)", !ctx_r3.cdkDrag() && "ml-2.5")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", active_r3 ? "chevron-down" : "chevron-right"); } } function AnnotationCardComponent_ng_container_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_ng_container_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_Conditional_13_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](0, AnnotationCardComponent_Conditional_13_ng_container_0_Template, 1, 0, "ng-container", 18); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const moreMenuBtn_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](28); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", moreMenuBtn_r5); } } function AnnotationCardComponent_ng_container_15_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_ng_container_17_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_ng_container_18_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 34); } } function AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 33); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("mousedown", function AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_Template_p_button_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.preventDefault()); })("click", function AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.clearAnnotationName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](3, AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_ng_template_3_Template, 1, 0, "ng-template", null, 12, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 3, "common.clearName"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](2, 5, "common.clearName"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](7, _c4)); } } function AnnotationCardComponent_ng_template_19_Conditional_1_For_9_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "li")(1, "button", 35, 13); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("mousedown", function AnnotationCardComponent_ng_template_19_Conditional_1_For_9_Template_button_mousedown_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.preventDefault()); })("click", function AnnotationCardComponent_ng_template_19_Conditional_1_For_9_Template_button_click_1_listener($event) { const suggestion_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); $event.stopPropagation(); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.selectNameSuggestion(suggestion_r9)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const suggestion_r9 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r3.clampedSuggestions().has(suggestion_r9) ? suggestion_r9 : undefined)("tooltipPosition", ctx_r3.clampedSuggestions().has(suggestion_r9) ? "left" : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", suggestion_r9, " "); } } function AnnotationCardComponent_ng_template_19_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 25)(1, "div", 28)(2, "input", 29, 10); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_click_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("input", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_input_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.refreshNameSuggestions)($event)); })("keydown.space", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_keydown_space_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.handleSpace)($event)); })("keydown.enter", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_keydown_enter_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation()($event)); })("keyup.enter", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_keyup_enter_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.updateAnnotationName)($event)); })("keydown.escape", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_keydown_escape_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation()($event)); })("keyup.escape", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_keyup_escape_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.cancelEditAnnotationName)($event)); })("blur", function AnnotationCardComponent_ng_template_19_Conditional_1_Template_input_blur_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.updateAnnotationName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](4, AnnotationCardComponent_ng_template_19_Conditional_1_Conditional_4_Template, 5, 8, "p-button", 30); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](5, "p-popover", 31, 11)(7, "ul", 32); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](8, AnnotationCardComponent_ng_template_19_Conditional_1_For_9_Template, 4, 3, "li", null, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("id", `annotation-${ctx_r3.annotation().id}-name`)("formControl", ctx_r3.annotationName); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("data-test-id", `annotation-card-input-${ctx_r3.annotation().id}-name`)("maxlength", ctx_r3.nameMaxLength); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r3.annotationName.value ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("appendTo", "body")("dismissable", false); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](ctx_r3.filteredNameSuggestions()); } } function AnnotationCardComponent_ng_template_19_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "span", 26, 14); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r3.isNameClamped() ? ctx_r3.annotation().name : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", ctx_r3.annotation().name, " "); } } function AnnotationCardComponent_ng_template_19_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r10 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "button", 36); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function AnnotationCardComponent_ng_template_19_Conditional_3_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r10); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameClick($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](1, "span", 37, 14); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("min-w-0 flex-1 cursor-pointer text-left")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r3.isNameClamped() ? ctx_r3.annotation().name : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", ctx_r3.annotation().name, " "); } } function AnnotationCardComponent_ng_template_19_Conditional_4_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function AnnotationCardComponent_ng_template_19_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](0, AnnotationCardComponent_ng_template_19_Conditional_4_ng_container_0_Template, 1, 0, "ng-container", 18); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); const visibilityBtn_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](26); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", visibilityBtn_r11); } } function AnnotationCardComponent_ng_template_19_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](1, AnnotationCardComponent_ng_template_19_Conditional_1_Template, 10, 7, "div", 25)(2, AnnotationCardComponent_ng_template_19_Conditional_2_Template, 3, 2, "span", 26)(3, AnnotationCardComponent_ng_template_19_Conditional_3_Template, 4, 4, "button", 27); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](4, AnnotationCardComponent_ng_template_19_Conditional_4_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r3.isEditing() ? 1 : ctx_r3.readOnly() ? 2 : 3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](!ctx_r3.isEditing() ? 4 : -1); } } function AnnotationCardComponent_ng_template_21_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](1, "lib-icon", 38); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("flex size-7 shrink-0 items-center justify-center rounded-full bg-(--p-app-surface-icon-holder)", ctx_r3.annotation().hidden && "opacity-80")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleProp"]("color", ctx_r3.accentColor()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", ctx_r3.iconName()); } } function AnnotationCardComponent_ng_template_23_div_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 41); } } function AnnotationCardComponent_ng_template_23_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 39); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](2, AnnotationCardComponent_ng_template_23_div_2_Template, 1, 0, "div", 40); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("order-first size-3 px-1.5 py-3 text-(--p-accordion-header-toggle-icon-hover-color) opacity-0", ctx_r3.readOnly() ? "pointer-events-none" : "cursor-grab transition-opacity delay-100 group-hover:opacity-100 active:cursor-grabbing")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("aria-hidden", ctx_r3.readOnly() || null)("aria-label", ctx_r3.readOnly() ? null : _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 4, "annotationCard.dragToReorder")); } } function AnnotationCardComponent_ng_template_25_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 43); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", ctx_r3.annotation().hidden ? "eye" : "eye-off"); } } function AnnotationCardComponent_ng_template_25_Template(rf, ctx) { if (rf & 1) { const _r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 42); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function AnnotationCardComponent_ng_template_25_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r12); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.annotation().hidden ? ctx_r3.show.emit() : ctx_r3.hide.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](2, AnnotationCardComponent_ng_template_25_ng_template_2_Template, 1, 1, "ng-template", null, 12, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn(ctx_r3.readOnly() && "pointer-events-none opacity-0")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](8, _c5))("dt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](12, _c8, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](10, _c7, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](9, _c6))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 6, ctx_r3.annotation().hidden ? "common.show" : "common.hide")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("aria-hidden", ctx_r3.readOnly() || null); } } function AnnotationCardComponent_ng_template_27_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 45); } } function AnnotationCardComponent_ng_template_27_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](2, AnnotationCardComponent_ng_template_27_ng_template_2_Template, 1, 0, "ng-template", null, 12, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const moreMenuTrigger_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](7, _c5))("dt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](11, _c8, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](9, _c7, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](8, _c6))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 5, "common.moreActions"))("libMenuTrigger", moreMenuTrigger_r13)("libMenuActions", ctx_r3.actions()); } } function AnnotationCardComponent_ng_template_29_Conditional_2_For_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 47)(1, "span", 49); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const name_r14 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](name_r14); } } function AnnotationCardComponent_ng_template_29_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 47)(1, "span", 48); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](4, AnnotationCardComponent_ng_template_29_Conditional_2_For_5_Template, 3, 1, "div", 47, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIdentity"]); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const relatedNames_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"]("", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](3, 1, "annotationCard.relativeTo"), ":"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](relatedNames_r15); } } function AnnotationCardComponent_ng_template_29_For_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 47)(1, "span", 48); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](4, "span", 50); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const measurement_r16 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"]("", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](3, 2, measurement_r16.name), ":"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](measurement_r16.value); } } function AnnotationCardComponent_ng_template_29_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 46); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](2, AnnotationCardComponent_ng_template_29_Conditional_2_Template, 6, 3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](3, AnnotationCardComponent_ng_template_29_For_4_Template, 6, 4, "div", 47, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); const relatedNames_r17 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"](ctx_r3.annotation().relatedNames); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](relatedNames_r17 && relatedNames_r17.length > 0 ? 2 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](ctx_r3.annotation().measurements); } } function AnnotationCardComponent_ng_template_31_For_2_Conditional_0_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 54); } if (rf & 2) { const action_r19 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", action_r19.icon)("pTooltip", action_r19.label); } } function AnnotationCardComponent_ng_template_31_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r18 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 53); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function AnnotationCardComponent_ng_template_31_For_2_Conditional_0_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r18); const action_r19 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"]().$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](action_r19.command == null ? null : action_r19.command($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](1, AnnotationCardComponent_ng_template_31_For_2_Conditional_0_ng_template_1_Template, 1, 2, "ng-template", null, 12, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const action_r19 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ariaLabel", action_r19.label)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](3, _c5))("disabled", action_r19.disabled); } } function AnnotationCardComponent_ng_template_31_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](0, AnnotationCardComponent_ng_template_31_For_2_Conditional_0_Template, 3, 4, "p-button", 52); } if (rf & 2) { const action_r19 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](action_r19.icon ? 0 : -1); } } function AnnotationCardComponent_ng_template_31_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 51); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](1, AnnotationCardComponent_ng_template_31_For_2_Template, 1, 1, null, null, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](ctx_r3.cardActions()); } } function AnnotationCardComponent_ng_template_33_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 55); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleProp"]("background-color", ctx_r3.selected() ? ctx_r3.accentColor() : ""); } } const ANNOTATION_TYPE_ICON_MAP = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.AnnotationSourceType.CYLINDER]: 'object-3d', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.AnnotationSourceType.HOLLOW_CYLINDER]: 'object-3d', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.AnnotationSourceType.STL]: 'object-3d' }; class AnnotationCardComponent { annotation = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "annotation" }] : [])); actions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)([], ...(ngDevMode ? [{ debugName: "actions" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "selected" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); menuTrigger = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(...(ngDevMode ? [undefined, { debugName: "menuTrigger" }] : [])); cdkDrag = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "cdkDrag" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); readOnly = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "readOnly" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); show = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); hide = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); goTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); updateName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); selectedChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); clicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); cancelClick = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.CancelClickDirective, ...(ngDevMode ? [{ debugName: "cancelClick" }] : [])); cdr = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.ChangeDetectorRef); nameInput = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameInput', ...(ngDevMode ? [{ debugName: "nameInput" }] : [])); nameLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameLabel', ...(ngDevMode ? [{ debugName: "nameLabel" }] : [])); suggestionsPopover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('suggestionsPopover', ...(ngDevMode ? [{ debugName: "suggestionsPopover" }] : [])); suggestionButtons = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChildren)('suggestionButton', ...(ngDevMode ? [{ debugName: "suggestionButtons" }] : [])); isEditing = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isEditing" }] : [])); annotationName = new _angular_forms__WEBPACK_IMPORTED_MODULE_6__.FormControl(''); nameMaxLength = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.ANNOTATION_NAME_MAX_LENGTH; isNameClamped = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isNameClamped" }] : [])); structureNameSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.ANNOTATION_STRUCTURE_NAMES[this.annotation().type] ?? [], ...(ngDevMode ? [{ debugName: "structureNameSuggestions" }] : [])); filteredNameSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "filteredNameSuggestions" }] : [])); /** Suggestions whose text is actually cut off by ellipsis in the dropdown, by name. */ clampedSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(new Set(), ...(ngDevMode ? [{ debugName: "clampedSuggestions" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.afterEveryRender)(() => { const element = this.nameLabel()?.nativeElement; if (!element) return; const clamped = element.scrollHeight > element.clientHeight; if (clamped !== this.isNameClamped()) this.isNameClamped.set(clamped); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.afterEveryRender)(() => { const clamped = new Set(this.suggestionButtons().filter(({ nativeElement }) => nativeElement.scrollWidth > nativeElement.clientWidth).map(({ nativeElement }) => nativeElement.textContent?.trim() ?? '')); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.isEqualSet)(clamped, this.clampedSuggestions())) this.clampedSuggestions.set(clamped); }); } ngOnInit() { this.annotationName.setValue(this.annotation().name); } ngAfterViewInit() { this.cancelClick()?.filteredClick.subscribe(event => this.clicked.emit(event)); } mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.buildCardPt)(this.pt(), this.getCardState()), ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.buildCardDt)(_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.DARK_CARD_THEME[this.getCardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); accentColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.annotation().hidden ? 'var(--p-text-muted-color)' : this.annotation().color, ...(ngDevMode ? [{ debugName: "accentColor" }] : [])); iconName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const { type } = this.annotation(); return ANNOTATION_TYPE_ICON_MAP[type] ?? type; }, ...(ngDevMode ? [{ debugName: "iconName" }] : [])); cardActions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.actions().filter(action => action.includeInCard), ...(ngDevMode ? [{ debugName: "cardActions" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn; contextMenu(event) { // NOTE: On Mac, ctrl+click triggers the contextmenu event, // but that conflicts with our multiselect functionality. // We must re-emit this as a click now if (event.ctrlKey) { event.preventDefault(); this.clicked.emit(event); return; } const trigger = this.menuTrigger(); if (!trigger) return; trigger.model.set(this.actions()); trigger.toggle(event); } handleCardDoubleClick(event) { const wrapper = event.currentTarget; if (this.isEditing() || (0,_card_theme_card_interaction__WEBPACK_IMPORTED_MODULE_17__.isInteractiveCardDescendant)(event, wrapper)) return; this.goTo.emit(); } handleNameClick(event) { event.stopPropagation(); event.preventDefault(); this.onEditAnnotationName(); this.cdr.markForCheck(); } handleEventPropagation(callback) { return event => { event.stopPropagation(); event.preventDefault(); callback?.(); this.cdr.markForCheck(); }; } handleSpace = () => { const value = this.annotationName.value ?? ''; if (value.length >= this.nameMaxLength) return; this.annotationName.setValue(value + ' '); }; onEditAnnotationName = () => { if (this.readOnly() || this.isEditing()) return; this.annotationName.setValue(this.annotation().name); this.menuTrigger()?.hide(); this.isEditing.set(true); this.refreshNameSuggestions(); setTimeout(() => { this.nameInput()?.nativeElement.focus(); this.syncSuggestionsPopover(); }); }; cancelEditAnnotationName = () => { this.isEditing.set(false); this.suggestionsPopover()?.hide(); }; /** Clears the field's current text (without saving) so a new name can be picked from the * suggestions list with the mouse alone, no backspacing required. */ clearAnnotationName = () => { this.annotationName.setValue(''); this.refreshNameSuggestions(); this.nameInput()?.nativeElement.focus(); }; updateAnnotationName = () => { const value = this.annotationName.value ?? ''; if (value.trim().length === 0) { this.cancelEditAnnotationName(); return; } this.isEditing.set(false); this.suggestionsPopover()?.hide(); this.updateName.emit(value); }; /** Narrows the type-specific structure-name list to whatever's currently typed. */ refreshNameSuggestions = () => { const allNames = this.structureNameSuggestions(); if (allNames.length === 0) { this.filteredNameSuggestions.set([]); } else { const query = (this.annotationName.value ?? '').trim().toLowerCase(); this.filteredNameSuggestions.set(query ? allNames.filter(name => name.toLowerCase().includes(query)) : allNames); } this.syncSuggestionsPopover(); }; selectNameSuggestion(name) { this.annotationName.setValue(name.slice(0, this.nameMaxLength)); this.updateAnnotationName(); } /** Shows/hides the structure-name suggestions panel, anchored to the name input. */ syncSuggestionsPopover() { const input = this.nameInput()?.nativeElement; const popover = this.suggestionsPopover(); if (!popover || !input) return; if (this.filteredNameSuggestions().length > 0) { popover.show(undefined, input); } else { popover.hide(); } } getCardState() { if (this.selected()) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.SELECTED; if (this.annotation().hidden) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DISABLED; return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DEFAULT; } static ɵfac = function AnnotationCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineComponent"]({ type: AnnotationCardComponent, selectors: [["lib-annotation-card"]], viewQuery: function AnnotationCardComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵviewQuerySignal"](ctx.cancelClick, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.CancelClickDirective, 5)(ctx.nameInput, _c0, 5)(ctx.nameLabel, _c1, 5)(ctx.suggestionsPopover, _c2, 5)(ctx.suggestionButtons, _c3, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵqueryAdvance"](5); } }, inputs: { annotation: [1, "annotation"], actions: [1, "actions"], pt: [1, "pt"], selected: [1, "selected"], menuTrigger: [1, "menuTrigger"], cdkDrag: [1, "cdkDrag"], readOnly: [1, "readOnly"] }, outputs: { show: "show", hide: "hide", goTo: "goTo", updateName: "updateName", selectedChange: "selectedChange", clicked: "clicked" }, decls: 35, vars: 18, consts: [["panel", ""], ["toggleicon", ""], ["headerTitle", ""], ["cardIcon", ""], ["dragHandle", ""], ["visibilityBtn", ""], ["moreMenuBtn", ""], ["contentMeasurements", ""], ["contentActions", ""], ["accentBar", ""], ["nameInput", ""], ["suggestionsPopover", ""], ["icon", ""], ["suggestionButton", ""], ["nameLabel", ""], ["data-test-id", "annotation-card-div-wrapper", 3, "click", "dblclick", "contextmenu"], [1, "grow", 3, "pt", "dt", "value"], ["libCancelClick", "", 3, "pt"], [4, "ngTemplateOutlet"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-2", "py-1"], [1, "relative", 3, "pt"], [1, "flex", "gap-3"], ["data-propagate-click", "", 3, "icon"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], [1, "min-w-0", "flex-1"], [1, "line-clamp-2", "min-w-0", "flex-1", "wrap-anywhere", 3, "pTooltip"], ["type", "button", "data-test-id", "annotation-card-button-name-trigger", "data-propagate-click", "", 3, "class"], [1, "flex", "min-w-0", "items-center", "gap-1"], ["pInputText", "", "data-propagate-click", "", 1, "border-primary-400", "w-full", "min-w-0", "bg-transparent", "py-0.5", "text-sm", "text-inherit", 3, "click", "input", "keydown.space", "keydown.enter", "keyup.enter", "keydown.escape", "keyup.escape", "blur", "id", "formControl"], ["type", "button", "data-propagate-click", "", "data-test-id", "annotation-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "pTooltip", "ariaLabel", "pt"], ["data-propagate-click", "", 3, "appendTo", "dismissable"], ["data-propagate-click", "", "data-test-id", "annotation-card-ul-name-suggestions", 1, "max-h-48", "w-56", "overflow-auto", "text-sm"], ["type", "button", "data-propagate-click", "", "data-test-id", "annotation-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "mousedown", "click", "pTooltip", "ariaLabel", "pt"], ["icon", "times", 1, "size-3"], ["type", "button", "data-propagate-click", "", "data-test-id", "annotation-card-button-name-suggestion", 1, "hover:bg-surface-800", "block", "w-full", "overflow-hidden", "rounded", "px-2", "py-1", "text-left", "text-ellipsis", "whitespace-nowrap", "text-inherit", 3, "mousedown", "click", "pTooltip", "tooltipPosition"], ["type", "button", "data-test-id", "annotation-card-button-name-trigger", "data-propagate-click", "", 3, "click"], [1, "line-clamp-2", "wrap-anywhere", 3, "pTooltip"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"], ["cdkDragHandle", "", "icon", "drag-handle"], ["class", "h-11 rounded-sm bg-(--p-app-dark-surface-base)", 4, "cdkDragPlaceholder"], [1, "h-11", "rounded-sm", "bg-(--p-app-dark-surface-base)"], ["data-test-id", "annotation-card-p-button-visibility", "data-propagate-click", "", "tooltipPosition", "left", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "pt", "dt", "pTooltip"], [1, "size-(--p-app-icon-size-xs)", 3, "icon"], ["data-test-id", "annotation-card-p-button-more-actions", "data-propagate-click", "", "tooltipPosition", "left", "severity", "secondary", "outlined", "", "size", "small", 3, "pt", "dt", "pTooltip", "libMenuTrigger", "libMenuActions"], ["icon", "ellipsis-v", 1, "size-(--p-app-icon-size-xxxs)", "text-(length:--p-app-icon-size-xxxs)"], [1, "flex", "grow", "flex-col", "gap-[3px]", "py-0", "text-[11px]"], [1, "flex", "gap-1"], [1, "text-color", "font-semibold"], [1, "ps-4", "text-(--p-accordion-content-muted-color)"], [1, "text-(--p-accordion-content-muted-color)"], [1, "-mt-2", "flex", "flex-col", "items-end"], ["data-test-id", "annotation-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "ariaLabel", "pt", "disabled"], ["data-test-id", "annotation-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "ariaLabel", "pt", "disabled"], ["tooltipPosition", "left", 1, "size-(--p-app-icon-size-xs)", 3, "icon", "pTooltip"], [1, "absolute", "top-0", "left-0", "h-full", "w-1"]], template: function AnnotationCardComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 15); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function AnnotationCardComponent_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.clicked.emit($event)); })("dblclick", function AnnotationCardComponent_Template_div_dblclick_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.handleCardDoubleClick($event)); })("contextmenu", function AnnotationCardComponent_Template_div_contextmenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.contextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](1, "p-accordion-panel", 16, 0)(3, "p-accordion-header", 17); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](4, AnnotationCardComponent_ng_container_4_Template, 1, 0, "ng-container", 18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](5, AnnotationCardComponent_Conditional_5_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](6, AnnotationCardComponent_ng_template_6_Template, 1, 3, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](8, "div", 19)(9, "div", 20); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](10, AnnotationCardComponent_ng_container_10_Template, 1, 0, "ng-container", 18)(11, AnnotationCardComponent_ng_container_11_Template, 1, 0, "ng-container", 18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](13, AnnotationCardComponent_Conditional_13_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](14, "p-accordion-content", 21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](15, AnnotationCardComponent_ng_container_15_Template, 1, 0, "ng-container", 18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](16, "div", 22); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](17, AnnotationCardComponent_ng_container_17_Template, 1, 0, "ng-container", 18)(18, AnnotationCardComponent_ng_container_18_Template, 1, 0, "ng-container", 18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](19, AnnotationCardComponent_ng_template_19_Template, 5, 2, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(21, AnnotationCardComponent_ng_template_21_Template, 2, 5, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(23, AnnotationCardComponent_ng_template_23_Template, 3, 6, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(25, AnnotationCardComponent_ng_template_25_Template, 4, 14, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(27, AnnotationCardComponent_ng_template_27_Template, 4, 13, "ng-template", null, 6, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(29, AnnotationCardComponent_ng_template_29_Template, 5, 2, "ng-template", null, 7, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(31, AnnotationCardComponent_ng_template_31_Template, 3, 0, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(33, AnnotationCardComponent_ng_template_33_Template, 1, 2, "ng-template", null, 9, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const headerTitle_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](20); const cardIcon_r21 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](22); const contentMeasurements_r22 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](30); const contentActions_r23 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](32); const accentBar_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](34); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx.cn("group flex w-full overflow-hidden", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", ctx.annotation().id); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx.cdkDrag() ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", headerTitle_r20); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); const moreMenuTrigger_r25 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"](ctx.menuTrigger()); const moreActions_r26 = ctx.actions(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](!ctx.isEditing() && moreMenuTrigger_r25 && moreActions_r26.length ? 13 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().content); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", contentMeasurements_r22); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", contentActions_r23); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionContent, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionPanel, _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_16__.AnnotationMenuTriggerDirective, primeng_button__WEBPACK_IMPORTED_MODULE_9__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.CancelClickDirective, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragHandle, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragPlaceholder, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.IconComponent, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, primeng_popover__WEBPACK_IMPORTED_MODULE_11__.Popover, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.FormControlDirective, primeng_tooltip__WEBPACK_IMPORTED_MODULE_12__.Tooltip, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputText, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 39860 /*!******************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/annotation-menu-item.service.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationMenuItemService: () => (/* binding */ AnnotationMenuItemService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _chamber_chamber_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../chamber/chamber.service */ 16592); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../colors/colors.service */ 39298); /* harmony import */ var _create_s_curve_dialog_create_s_curve_dialog_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../create-s-curve-dialog/create-s-curve-dialog.component */ 24340); /* harmony import */ var _device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../device-sizing-chart/device-sizing-chart-dialog.service */ 26755); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _relative_measurements_relative_measurements_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../relative-measurements/relative-measurements.service */ 79408); /* harmony import */ var _s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../s-curve-relative-measurements/s-curve-relative-measurements.service */ 17464); /* harmony import */ var _volume_viewer_annotation_actors_annotation_updaters_constants__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../volume-viewer/annotation-actors/annotation-updaters/constants */ 55127); /* harmony import */ var _volume_viewer_cpr_cpr_service__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../volume-viewer/cpr/cpr.service */ 26144); /* harmony import */ var _volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../volume-viewer/viewport-ids */ 85309); /* harmony import */ var _volume_viewer_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../volume-viewer/volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _window_window_service__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../window/window.service */ 26914); /* harmony import */ var _model_geometry_service__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./model-geometry.service */ 27113); const DESTRUCTIVE_CLASSES = 'text-(--p-app-status-danger)'; const REFERENCE_LINES_ICON = 'reference-lines'; const RELATIVE_MEASUREMENT_LABEL_CLASS = 'whitespace-nowrap'; const ANNOTATION_LABEL_CLASS = 'max-w-64 overflow-hidden text-ellipsis whitespace-nowrap'; const ALIGN_VIEWS = [{ axis: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportAxisState.TOPLEFTMAIN, color: 'var(--p-app-viewport-axis-axial)', key: 'axial' }, { axis: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportAxisState.MIDDLEMAIN, color: 'var(--p-app-viewport-axis-coronal)', key: 'coronal' }, { axis: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportAxisState.BOTTOMLEFTMAIN, color: 'var(--p-app-viewport-axis-sagittal)', key: 'sagittal' }]; class AnnotationMenuItemService { annotationFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.AnnotationFacade); chamberService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_chamber_chamber_service__WEBPACK_IMPORTED_MODULE_14__.ChamberService); colorsService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_15__.ColorsService); dialogService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__.DialogService); sCurveFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.SCurveFacade); uiFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.UiFacade); interactionModeService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_18__.InteractionModeService); relativeMeasurements = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_relative_measurements_relative_measurements_service__WEBPACK_IMPORTED_MODULE_19__.RelativeMeasurementsService); sCurveRelativeMeasurements = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_20__.SCurveRelativeMeasurementsService); document = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT); viewer = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_volume_viewer_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_24__.VolumeViewerOrchestrator); cprService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_volume_viewer_cpr_cpr_service__WEBPACK_IMPORTED_MODULE_22__.CprService); translate = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); windowService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_window_window_service__WEBPACK_IMPORTED_MODULE_25__.WindowService); confirmationService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_4__.ConfirmationService); viewportStore = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.viewportStore); modelGeometry = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_model_geometry_service__WEBPACK_IMPORTED_MODULE_26__.ModelGeometryService); devOptions = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_6__.DevelopmentOptionsService); isDevBuild = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.IS_DEV_BUILD); deviceSizingChart = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_17__.DeviceSizingChartDialogService); selectedAnnotationIds = this.annotationFacade.selectedIds; hiddenSelectedAnnotationIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.annotationFacade.selectedAnnotations().filter(({ hidden }) => hidden).map(({ id }) => id), ...(ngDevMode ? [{ debugName: "hiddenSelectedAnnotationIds" }] : [])); visibleSelectedAnnotationIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.annotationFacade.selectedAnnotations().filter(({ hidden }) => !hidden).map(({ id }) => id), ...(ngDevMode ? [{ debugName: "visibleSelectedAnnotationIds" }] : [])); annotationIdsByVisibility = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const annotations = this.annotationFacade.annotations(); const annotationIdsVisibilities = { hiddenIds: [], visibleIds: [] }; for (const { hidden, id } of annotations) { const arrayToPush = hidden ? annotationIdsVisibilities.hiddenIds : annotationIdsVisibilities.visibleIds; arrayToPush.push(id); } return annotationIdsVisibilities; }, ...(ngDevMode ? [{ debugName: "annotationIdsByVisibility" }] : [])); selectedSCurveIds = this.sCurveFacade.selectedIds; sCurveIdsByVisibility = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const sCurves = this.sCurveFacade.sCurves(); const sCurveIdsVisibilities = { hiddenIds: [], visibleIds: [] }; for (const { hidden, id } of sCurves) { const arrayToPush = hidden ? sCurveIdsVisibilities.hiddenIds : sCurveIdsVisibilities.visibleIds; arrayToPush.push(id); } return sCurveIdsVisibilities; }, ...(ngDevMode ? [{ debugName: "sCurveIdsByVisibility" }] : [])); showAnnotation(annotationId) { this.annotationFacade.setAnnotationsVisibility([annotationId], true); } hideAnnotation(annotationId) { this.annotationFacade.setAnnotationsVisibility([annotationId], false); } goToAnnotation(annotationId) { this.viewer.goToAnnotation(annotationId); } updateAnnotationName(annotationId, newName) { const annotation = this.annotationFacade.annotationMap()[annotationId]; if (annotation) { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_12__.rename)(annotation, newName)); } } confirmDeleteSelectedAnnotations(target) { const selectedIds = this.selectedAnnotationIds(); if (selectedIds.length === 0) return; this.confirmDeletion(selectedIds, selectedIds.length > 1 ? 'selected' : 'single', target); } confirmDeleteSingleAnnotation(annotationId, target) { this.confirmDeletion([annotationId], 'single', target); } buildRenameLabels() { return { cancelLabel: this.translate.instant('common.cancel'), header: this.translate.instant('annotationMenu.renameHeader'), inputLabel: this.translate.instant('common.name'), saveLabel: this.translate.instant('common.save') }; } /** "Rename" for a type with preset names: a submenu-only row (no click action of its own, * same as every other submenu item here) listing each preset plus a trailing "Custom…" * entry that opens the popup dialog. Types with no suggestions fall back to a plain item * whose click opens the dialog directly - there'd be nothing to show in a submenu. */ renameMenuItem(suggestions, onSelectSuggestion, openDialog) { const label = this.translate.instant('common.rename'); if (!suggestions || suggestions.length === 0) { return { command: openDialog, icon: 'typography', label }; } return { icon: 'typography', items: [...suggestions.map(name => ({ command: () => onSelectSuggestion(name), label: name })), { separator: true }, { command: openDialog, label: this.translate.instant('annotationMenu.renameCustom') }], label }; } // eslint-disable-next-line sonarjs/cyclomatic-complexity menuItemsForAnnotation(annotation, pointIndex) { const renameLabels = this.buildRenameLabels(); const menuItems = [{ command: () => { this.viewer.goToAnnotation(annotation.id); }, disabled: !(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_9__.isRenderable)(annotation), icon: 'target', includeInCard: true, label: this.translate.instant('annotationMenu.goToAnnotation', { name: annotation.name }) }]; const relativeItems = this.relativeMeasurementsSubmenu(annotation); if (relativeItems.length > 0) { menuItems.push({ separator: true }, { icon: 'relative-measurements', items: relativeItems, label: this.translate.instant('annotationMenu.relativeMeasurements.label') }); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsObject3D)(annotation)) { menuItems.push({ separator: true }, ...this.object3DMenuItems(annotation)); } if (annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.AnnotationSourceType.CLOSED_SPLINE) { menuItems.push({ separator: true }, { command: () => this.deviceSizingChart.open(annotation.id), icon: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.TABLE, includeInCard: true, label: this.translate.instant('annotationMenu.deviceSizingChart') }, { command: () => { this.sCurveFacade.selectSCurves([annotation.id]); this.uiFacade.openSidebarSection(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.SidebarSection.SCURVE); }, icon: 's-curve', includeInCard: true, label: this.translate.instant('annotationMenu.optimalProjectionCurve') }); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsSpline)(annotation) && this.interactionModeService.interactionMode().type === 'select') { menuItems.push({ command: () => { this.interactionModeService.startAddingPoints(annotation.id); }, icon: 'plus', label: this.translate.instant('annotationMenu.addPointsToSpline') }); if (pointIndex !== undefined && annotation.points.length > 2) { menuItems.push({ command: () => { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_12__.removePointAt)(annotation, pointIndex)); }, icon: 'minus', label: this.translate.instant('annotationMenu.removePointFromSpline') }); } } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsSpline)(annotation)) { menuItems.push({ command: () => { this.cprService.start(annotation); this.uiFacade.openSidebarSection(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.SidebarSection.PLANAR_REFORMATION); }, icon: 'curve', label: this.translate.instant('annotationMenu.planarReformation') }); } menuItems.push({ separator: true }, { command: () => { this.annotationFacade.setAnnotationsVisibility([annotation.id], annotation.hidden); }, icon: annotation.hidden ? 'eye' : 'eye-off', label: annotation.hidden ? this.translate.instant('common.show') : this.translate.instant('common.hide') }); const selectedIdCount = this.selectedAnnotationIds().length; if (selectedIdCount > 1) { const hiddenIds = this.hiddenSelectedAnnotationIds(); const visibleIds = this.visibleSelectedAnnotationIds(); menuItems.push({ separator: true }, { command: () => { this.annotationFacade.setAnnotationsVisibility(hiddenIds, true); }, disabled: hiddenIds.length === 0, icon: 'eye', label: this.translate.instant('annotationMenu.showSelectedAnnotations', { count: selectedIdCount }) }, { command: () => { this.annotationFacade.setAnnotationsVisibility(visibleIds, false); }, disabled: visibleIds.length === 0, icon: 'eye-off', label: this.translate.instant('annotationMenu.hideSelectedAnnotations', { count: selectedIdCount }) }, { separator: true }); } menuItems.push(this.renameMenuItem(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.ANNOTATION_STRUCTURE_NAMES[annotation.type], name => this.updateAnnotationName(annotation.id, name), () => this.annotationFacade.openRenameDialog(annotation, renameLabels)), { annotation, customType: 'color-swatch', icon: 'palette' }, { items: [{ annotation, customType: 'color-swatch-full' }], label: this.translate.instant('annotationMenu.otherColor') }, { separator: true }); if (selectedIdCount > 1) { menuItems.push({ command: event => this.confirmDeleteSelectedAnnotations(event.originalEvent?.target ?? undefined), icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteSelectedAnnotations', { count: selectedIdCount }), linkClass: DESTRUCTIVE_CLASSES }); } else { menuItems.push({ command: event => this.confirmDeleteSingleAnnotation(annotation.id, event.originalEvent?.target ?? undefined), icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteAnnotation'), linkClass: DESTRUCTIVE_CLASSES }); } return menuItems; } object3DMenuItems(annotation) { const items = [{ command: () => this.viewer.openEditOrientation(annotation.id), disabled: annotation.locked, icon: 'rotation-3d', label: this.translate.instant('annotationMenu.editOrientation.label') }, { disabled: annotation.locked, icon: 'align-horizontal-center', items: this.alignWithItems(annotation), label: this.translate.instant('annotationMenu.alignWith') }, { command: () => this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_12__.toggleLock)(annotation)), icon: annotation.locked ? 'lock-open' : 'lock', label: annotation.locked ? this.translate.instant('annotationMenu.unlock') : this.translate.instant('annotationMenu.lock') }]; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsStl)(annotation)) { items.unshift(this.modelGeometrySubmenu(annotation)); } return items; } /** * Build the "Align with …" menu items (orthogonal views and closed splines). * Shared by the context-menu submenu and the orientation dialog button. */ alignWithItems(target, onAfterAlign) { const viewItems = ALIGN_VIEWS.map(({ axis, color, key }) => ({ command: () => { this.modelGeometry.alignWithViewport(target, axis); onAfterAlign?.(); }, disabled: target.locked, icon: 'fullscreen', iconStyle: { color }, label: this.translate.instant(`annotationMenu.editOrientation.views.${key}`) })); const splineItems = this.annotationFacade.annotations().filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsClosedSpline)(annotation)).map(spline => ({ command: () => { this.modelGeometry.alignWithSpline(target, spline); onAfterAlign?.(); }, disabled: target.locked, icon: 'closed-spline', iconStyle: { color: spline.color }, label: spline.name })); return splineItems.length > 0 ? [...viewItems, { separator: true }, ...splineItems] : viewItems; } modelGeometrySubmenu(stl) { const label = key => this.translate.instant(`annotationMenu.modelGeometry.${key}`); return { disabled: stl.locked, icon: 'architecture', items: [{ command: () => this.modelGeometry.flipAxis(stl), icon: 'sync', label: label('flipAxis') }, { separator: true }, { command: () => this.modelGeometry.resetOrientation(stl), icon: 'refresh', label: label('resetOrientation') }], label: label('label') }; } menuItemsForPanelAnnotations(expandCallback) { return (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { hiddenIds, visibleIds } = this.annotationIdsByVisibility(); const ids = [...visibleIds, ...hiddenIds]; if (ids.length === 0) return []; return [{ command: () => this.annotationFacade.setAnnotationsVisibility(hiddenIds, true), disabled: hiddenIds.length === 0, icon: 'eye', label: this.translate.instant('annotationMenu.showAllAnnotationsOnScreen') }, { command: () => this.annotationFacade.setAnnotationsVisibility(visibleIds, false), disabled: visibleIds.length === 0, icon: 'eye-off', label: this.translate.instant('annotationMenu.hideAllAnnotationsOnScreen') }, { separator: true }, { command: () => expandCallback(ids), icon: 'eye', label: this.translate.instant('annotationMenu.showAllCardsDetails') }, { command: () => expandCallback([]), icon: 'eye-off', label: this.translate.instant('annotationMenu.hideAllCardsDetails') }, { separator: true }, { command: event => this.confirmDeletion(ids, 'all', event.originalEvent?.target ?? undefined), icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteAllAnnotations'), linkClass: DESTRUCTIVE_CLASSES }]; }); } /** Picks the first palette color not already used by an existing s-curve * (spline-derived or control-point) or relative measurement, so a * newly-created curve never duplicates a color already on the graph. */ nextAvailableSCurveColor() { const usedColors = new Set([...this.sCurveFacade.relativeMeasurements().map(({ color }) => color), ...this.sCurveFacade.sCurves().map(({ color }) => color)]); const available = this.colorsService.colors.find(color => !usedColors.has(color)); return available ?? this.colorsService.currentColor(); } openCreateSCurveDialog(pointCount) { const dialog = this.dialogService.open(_create_s_curve_dialog_create_s_curve_dialog_component__WEBPACK_IMPORTED_MODULE_16__.CreateSCurveDialogComponent, { closeOnEscape: true, header: this.translate.instant(pointCount === 1 ? 'annotationMenu.createOnePointSCurve' : 'annotationMenu.createTwoPointSCurve'), inputValues: { pointCount }, modal: true, width: '360px' }); dialog?.onClose.subscribe(controlPoints => { if (!controlPoints) return; const existingNames = this.sCurveFacade.sCurves().map(({ name }) => name); const sCurve = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.controlPointSCurve)({ color: this.nextAvailableSCurveColor(), controlPoints, hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.incrementName)(pointCount === 1 ? 'One-point S-curve' : 'Two-point S-curve', existingNames, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.ANNOTATION_NAME_MAX_LENGTH) }); this.sCurveFacade.addSCurve(sCurve); this.sCurveFacade.selectSCurves([sCurve.id]); }); } openEditSCurveViewsDialog(sCurve) { const pointCount = sCurve.controlPoints.length; const dialog = this.dialogService.open(_create_s_curve_dialog_create_s_curve_dialog_component__WEBPACK_IMPORTED_MODULE_16__.CreateSCurveDialogComponent, { closeOnEscape: true, header: this.translate.instant(pointCount === 1 ? 'annotationMenu.createOnePointSCurve' : 'annotationMenu.createTwoPointSCurve'), inputValues: { initialControlPoints: sCurve.controlPoints, pointCount }, modal: true, width: '360px' }); dialog?.onClose.subscribe(controlPoints => { if (!controlPoints) return; this.sCurveFacade.updateSCurve({ controlPoints, id: sCurve.id }); }); } menuItemsForPanelSCurves(expandCallback) { return (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { hiddenIds, visibleIds } = this.sCurveIdsByVisibility(); const ids = [...visibleIds, ...hiddenIds]; const items = [{ command: () => this.openCreateSCurveDialog(1), icon: 's-curve', label: this.translate.instant('annotationMenu.createOnePointSCurve') }, { command: () => this.openCreateSCurveDialog(2), icon: 's-curve', label: this.translate.instant('annotationMenu.createTwoPointSCurve') }]; if (ids.length === 0) return items; items.push({ separator: true }, { command: () => { this.sCurveFacade.setSCurveVisibility(hiddenIds, true); }, disabled: hiddenIds.length === 0, icon: 'eye', label: this.translate.instant('annotationMenu.showAllSCurvesOnGraph') }, { command: () => { this.sCurveFacade.setSCurveVisibility(visibleIds, false); }, disabled: visibleIds.length === 0, icon: 'eye-off', label: this.translate.instant('annotationMenu.hideAllSCurvesOnGraph') }, { separator: true }); if (expandCallback !== undefined) { items.push({ command: () => expandCallback(ids), icon: 'eye', label: this.translate.instant('annotationMenu.showAllCardsDetails') }, { command: () => expandCallback([]), icon: 'eye-off', label: this.translate.instant('annotationMenu.hideAllCardsDetails') }, { separator: true }); } // Spline-derived s-curves are synced from their spline annotation and // would just reappear — only control-point (from-scratch) curves are // actually deletable here. const controlPointIds = this.sCurveFacade.sCurves().filter(sCurve => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.sCurveIsControlPoint)(sCurve)).map(({ id }) => id); items.push({ command: () => this.sCurveFacade.deleteSCurves(controlPointIds), disabled: controlPointIds.length === 0, icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteAllSCurves'), linkClass: DESTRUCTIVE_CLASSES }); return items; }); } confirmDeletion(ids, mode, target) { const translationKeyByMode = { all: 'annotationMenu.confirmDeleteAll', selected: 'annotationMenu.confirmDeleteSelected', single: 'annotationMenu.confirmDeleteAnnotation' }; const translationKey = translationKeyByMode[mode]; this.confirmationService.confirm({ accept: () => this.annotationFacade.deleteAnnotations(ids), acceptButtonProps: { label: this.translate.instant(`${translationKey}.cta.accept`), severity: 'danger' }, acceptLabel: this.translate.instant(`${translationKey}.cta.accept`), defaultFocus: 'accept', header: this.translate.instant(`${translationKey}.title`), icon: 'exclamation-triangle', message: this.translate.instant(`${translationKey}.message`, { count: ids.length }), rejectButtonProps: { label: this.translate.instant('common.cancel'), outlined: true, severity: 'secondary' }, target: target ?? undefined }); } menuItemsForViewport() { const { hiddenIds, visibleIds } = this.annotationIdsByVisibility(); const { annotationFacade, viewportStore } = this; const items = [{ command: () => this.viewer.resetAngulations(), icon: 'refresh', label: this.translate.instant('viewerMenu.cta.resetAngulations') }, { command: () => this.chamberService.createNewChamber({ angulation: this.viewportStore.viewportAngulations[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportAxisState.MIDDLEMAIN](), ax: this.viewportStore.ax(), crosshairRotation: this.viewportStore.viewportCrosshairRotations[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportAxisState.MIDDLEMAIN](), intersection: this.viewportStore.intersection(), isocenter: this.viewportStore.isocenter(), isPosterior: this.viewportStore.isPosterior() }), icon: 'camera', label: this.translate.instant('viewportButton.addChamberLabel') }, { separator: true }, { command: () => this.annotationFacade.setAnnotationsVisibility(hiddenIds, true), disabled: hiddenIds.length === 0, icon: 'eye', label: this.translate.instant('annotationMenu.showAllAnnotationsOnScreen') }, { command: () => this.annotationFacade.setAnnotationsVisibility(visibleIds, false), disabled: visibleIds.length === 0, icon: 'eye-off', label: this.translate.instant('annotationMenu.hideAllAnnotationsOnScreen') }, { separator: true }]; const showCrosshairs = this.viewportStore.showCrosshairs(); if (showCrosshairs) { items.push({ command: () => { this.viewportStore.updateCrosshairVisibility(false); }, icon: REFERENCE_LINES_ICON, label: this.translate.instant('viewerMenu.cta.hideReferencePlanes') }); } else { items.push({ command: () => { this.viewportStore.updateCrosshairVisibility(true); }, icon: REFERENCE_LINES_ICON, label: this.translate.instant('viewerMenu.cta.showReferencePlanes') }); } items.push({ disabled: true, icon: 'mouse-pointer', label: this.translate.instant('viewerMenu.cta.showHideOnScreenControls') }, { command: () => this.saveScreenshots(), icon: 'screenshot', label: this.translate.instant('viewerMenu.cta.saveScreenshots') }, { command: () => this.windowService.toggleFullscreen(), icon: 'expand', label: this.windowService.isFullscreen() ? this.translate.instant('viewerMenu.cta.exitFullscreen') : this.translate.instant('viewerMenu.cta.fullscreen') }, { separator: true }, { customType: 'slider', icon: 'screen-rotation', label: this.translate.instant('viewerMenu.cta.viewRotation'), slider: { max: 180, min: -180, onReset: () => { this.viewportStore.rotateAX(0); }, onSliderChange: value => { this.viewportStore.rotateAX(this.viewportStore.isPosterior() ? -value : value); }, showReset: true, step: 1, get value() { return viewportStore.isPosterior() ? -viewportStore.ax() : viewportStore.ax(); } } }, { separator: true }, { customType: 'slider', icon: 'pencil', label: this.translate.instant('viewerMenu.cta.annotationSize'), showReset: false, slider: { max: 5, min: 0.5, onReset: () => { this.annotationFacade.setAnnotationSize(_volume_viewer_annotation_actors_annotation_updaters_constants__WEBPACK_IMPORTED_MODULE_21__.DEFAULT_ANNOTATION_RADIUS); }, onSliderChange: value => { this.annotationFacade.setAnnotationSize(value); }, showReset: true, step: 0.1, get value() { return annotationFacade.annotationSize(); } } }, { customType: 'slider', icon: REFERENCE_LINES_ICON, label: this.translate.instant('viewerMenu.cta.crosshairSize'), showReset: false, slider: { max: 10, min: 1, onReset: () => { this.viewportStore.updateCrosshairSize(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_CROSSHAIR_SIZE); }, onSliderChange: value => { this.viewportStore.updateCrosshairSize(value); }, showReset: true, step: 0.1, get value() { return viewportStore.crosshairSize(); } } }, { separator: true }, { customType: 'toggle', icon: 'posterior', label: this.translate.instant('viewerMenu.cta.posterior'), toggle: { onChange: () => { this.viewer.updateIsPosterior(!this.viewer.isPosterior()); }, value: this.viewer.isPosterior() } }, { separator: true }, { items: [{ command: () => this.viewer.toggleEndoDevPanel(), label: 'Endo Preset Tuner' }, { command: () => this.viewer.toggleVascularDevPanel(), label: 'Vascular Render Tuner' }, { command: () => this.viewer.toggleRenderQualityDevPanel(), label: 'Render Quality Tuner' }, ...(this.isDevBuild ? [{ customType: 'toggle', icon: 'refresh', label: 'Clear local DICOM on startup', toggle: { onChange: value => this.devOptions.set('clearDicomCacheOnStartup', value), value: this.devOptions.clearDicomCacheOnStartup() } }] : [])], label: 'Advanced' }); return items; } menuItemsForAngulationMenu(viewportAxisState) { const items = [{ command: () => this.viewer.copyAngulations(viewportAxisState), icon: 'copy', label: this.translate.instant('viewerMenu.cta.copyAngulations') }]; return items; } menuItemsForSCurve(sCurve) { // Not marked `includeInCard` - the s-curve card already renders its own // dedicated visibility button in the header, so including it here too // would duplicate it in the card's expanded content-actions column. const items = [{ command: () => { this.sCurveFacade.setSCurveVisibility([sCurve.id], sCurve.hidden); }, icon: sCurve.hidden ? 'eye' : 'eye-off', label: sCurve.hidden ? this.translate.instant('common.show') : this.translate.instant('common.hide') }]; const otherCurves = this.sCurveFacade.sCurves().filter(other => other.id !== sCurve.id); if (otherCurves.length > 0) { items.push({ separator: true }, { icon: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.ANGLE, items: otherCurves.map(other => ({ command: () => this.sCurveRelativeMeasurements.createAngle(sCurve, other), icon: other.type === 'spline' ? _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.CLOSEDSPLINE : _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.SCURVE, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translate.instant('annotationMenu.sCurveRelativeMeasurements.angleTo') }, { icon: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.POINT, items: otherCurves.map(other => ({ command: () => this.sCurveRelativeMeasurements.createIntersection(sCurve, other), icon: other.type === 'spline' ? _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.CLOSEDSPLINE : _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.UiSvgIcon.SCURVE, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translate.instant('annotationMenu.sCurveRelativeMeasurements.intersectionWith') }); } // Spline-derived s-curves inherit the spline's name / color / etc if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.sCurveIsControlPoint)(sCurve)) { const renameLabels = this.buildRenameLabels(); items.push({ command: () => this.openEditSCurveViewsDialog(sCurve), icon: 'pencil', label: this.translate.instant('annotationMenu.editViews') }, { command: () => this.sCurveFacade.openRenameDialog(sCurve, renameLabels), icon: 'typography', label: this.translate.instant('common.rename') }, { annotation: sCurve, customType: 'color-swatch', icon: 'palette' }, { items: [{ annotation: sCurve, customType: 'color-swatch-full' }], label: this.translate.instant('annotationMenu.otherColor') }); const selectedIds = this.selectedSCurveIds(); const selectedIdCount = selectedIds.length; if (selectedIdCount > 1) { const selectedControlPointIds = this.sCurveFacade.sCurves().filter(curve => selectedIds.includes(curve.id) && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.sCurveIsControlPoint)(curve)).map(({ id }) => id); items.push({ command: () => this.sCurveFacade.deleteSCurves(selectedControlPointIds), disabled: selectedControlPointIds.length === 0, icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteSelectedSCurves', { count: selectedControlPointIds.length }), linkClass: DESTRUCTIVE_CLASSES }); } else { items.push({ command: () => this.sCurveFacade.deleteSCurves([sCurve.id]), icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteSCurve'), linkClass: DESTRUCTIVE_CLASSES }); } } return items; } menuItemsForSCurveRelativeMeasurement(measurement) { const renameLabels = this.buildRenameLabels(); return [{ command: () => this.sCurveRelativeMeasurements.goTo(measurement), disabled: !this.sCurveRelativeMeasurements.hasGoToTarget(measurement), icon: 'target', label: this.translate.instant('annotationMenu.goToAnnotation', { name: measurement.name }) }, // Not marked `includeInCard` - the measurement card already renders its own // dedicated visibility button in the header, so including it here too // would duplicate it in the card's expanded content-actions column. { command: () => { this.sCurveFacade.updateRelativeMeasurement({ hidden: !measurement.hidden, id: measurement.id }); }, icon: measurement.hidden ? 'eye' : 'eye-off', label: measurement.hidden ? this.translate.instant('common.show') : this.translate.instant('common.hide') }, { command: () => this.sCurveFacade.openRenameDialog(measurement, renameLabels), icon: 'typography', label: this.translate.instant('common.rename') }, { annotation: measurement, customType: 'color-swatch', icon: 'palette' }, { items: [{ annotation: measurement, customType: 'color-swatch-full' }], label: this.translate.instant('annotationMenu.otherColor') }, { command: () => this.sCurveFacade.deleteSCurves([measurement.id]), icon: 'trash', iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('annotationMenu.deleteSCurveRelativeMeasurement'), linkClass: DESTRUCTIVE_CLASSES }]; } saveScreenshots() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const timestamp = new Date().toISOString().replaceAll(':', '-').replaceAll('.', '-'); yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.saveScreenshots)({ document: _this.document, outputFileName: `tomoverse-screenshots-${timestamp}.zip`, selectors: ['#' + _volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_23__.VIEWPORT_IDS.AXIAL, '#' + _volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_23__.VIEWPORT_IDS.CORONAL, '#' + _volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_23__.VIEWPORT_IDS.SAGITTAL, '#' + _volume_viewer_viewport_ids__WEBPACK_IMPORTED_MODULE_23__.VIEWPORT_IDS.REFORMAT] }); })(); } // eslint-disable-next-line sonarjs/cyclomatic-complexity relativeMeasurementsSubmenu(annotation) { const otherAnnotations = this.annotationFacade.annotations().filter(other => other.id !== annotation.id); const menuItems = []; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsClosedSpline)(annotation)) { const otherSplines = otherAnnotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsClosedSpline)(annotation)); if (otherSplines.length > 0) { menuItems.push({ icon: 'angle', items: otherSplines.map(other => ({ command: () => { this.relativeMeasurements.angleBetweenSplines(annotation, other); }, icon: other.type, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translateLabel('angleBetweenSplines') }, { icon: 'angle', items: otherSplines.map(other => ({ command: () => { this.relativeMeasurements.angleBetweenSplineAxes(annotation, other); }, icon: other.type, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translateLabel('angleBetweenSplineAxes') }); } } if (annotation.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.AnnotationSourceType.POINT) { menuItems.push({ command: () => { this.relativeMeasurements.attachedDistance(annotation); }, icon: 'distance', label: this.translateLabel('attachedDistance'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }, { command: () => { this.relativeMeasurements.attachedPoint(annotation); }, icon: 'point', label: this.translateLabel('attachedPoint'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }, { command: () => { this.relativeMeasurements.attachedSpline(annotation); }, icon: 'open-spline', label: this.translateLabel('attachedSpline'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }, { command: () => { this.relativeMeasurements.centerDistance(annotation); }, icon: 'distance', label: this.translateLabel('centerDistance'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsSpline)(annotation) || annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.AnnotationSourceType.ANGLE) { menuItems.push({ command: () => { this.relativeMeasurements.chord(annotation); }, icon: 'distance', label: this.translateLabel('chord'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } if (annotation.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.AnnotationSourceType.POINT) { menuItems.push({ command: () => { this.relativeMeasurements.closestDistance(annotation); }, icon: 'distance', label: this.translateLabel('closestDistanceToOneAnnotation'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsPoint)(annotation)) { const otherSplines = otherAnnotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsSpline)(annotation)); if (otherSplines.length > 0) { menuItems.push({ icon: 'distance', items: otherSplines.map(other => ({ command: () => { this.relativeMeasurements.projectedDistanceFromPoint(other, annotation); }, icon: other.type, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translateLabel('projectedDistanceFromPoint'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsSpline)(annotation)) { menuItems.push({ command: () => { this.relativeMeasurements.curvaturePoint(annotation); }, icon: 'point', label: this.translateLabel('curvaturePoint'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }, { command: () => { this.relativeMeasurements.projectedDistance(annotation); }, icon: 'distance', label: this.translateLabel('projectedDistance'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); const otherPoints = otherAnnotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsPoint)(annotation)); if (otherPoints.length > 0) { menuItems.push({ icon: 'distance', items: otherPoints.map(other => ({ command: () => { this.relativeMeasurements.projectedDistanceFromPoint(annotation, other); }, icon: other.type, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translateLabel('projectedDistanceFromPoint'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } } // We aren't supporting Object3D with distance between currently, // this may come in a future ticket. const otherNonObject3Ds = otherAnnotations.filter(annotation => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsObject3D)(annotation)); if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.annotationIsObject3D)(annotation) && otherNonObject3Ds.length > 0) { menuItems.push({ icon: 'distance', items: otherNonObject3Ds.map(other => ({ command: () => { this.relativeMeasurements.closestDistanceBetween(annotation, other); }, icon: other.type, iconStyle: { color: other.color }, label: other.name, labelClass: ANNOTATION_LABEL_CLASS })), label: this.translateLabel('closestDistanceBetweenAnnotations'), labelClass: RELATIVE_MEASUREMENT_LABEL_CLASS }); } return menuItems.toSorted((a, b) => (a.label ?? 'z').localeCompare(b.label ?? 'z')); } translateLabel(key) { return this.translate.instant(`annotationMenu.relativeMeasurements.${key}`); } static ɵfac = function AnnotationMenuItemService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationMenuItemService)(); }; static ɵprov = /*@__PURE__*/_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: AnnotationMenuItemService, factory: AnnotationMenuItemService.ɵfac }); } /***/ }, /***/ 45731 /*!*******************************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/components/annotation-menu-item.component.ts ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationMenuItemComponent: () => (/* binding */ AnnotationMenuItemComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_ripple__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/ripple */ 73271); /* harmony import */ var primeng_slider__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/slider */ 31486); /* harmony import */ var primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/toggleswitch */ 79945); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../colors/colors.service */ 39298); /* harmony import */ var _color_swatch_menu_item_color_swatch_menu_item_component__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./color-swatch-menu-item/color-swatch-menu-item.component */ 75971); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ root: "size-7.5 p-0" }); function AnnotationMenuItemComponent_Case_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function AnnotationMenuItemComponent_Case_0_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "lib-color-swatch-menu-item", 5); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("annotation", ctx_r1.item().annotation)("colors", ctx_r1.fullColors); } } function AnnotationMenuItemComponent_Case_1_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function AnnotationMenuItemComponent_Case_1_Template_span_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "lib-icon", 7)(2, "lib-color-swatch-menu-item", 8); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("icon", ctx_r1.item().icon ?? "palette")("iconStyle", ctx_r1.item().iconStyle); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("annotation", ctx_r1.item().annotation)("colors", ctx_r1.colors); } } function AnnotationMenuItemComponent_Case_2_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function AnnotationMenuItemComponent_Case_2_Template_span_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](4, "p-toggleswitch", 11); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("ngModelChange", function AnnotationMenuItemComponent_Case_2_Template_p_toggleswitch_ngModelChange_4_listener($event) { let tmp_2_0; _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]((tmp_2_0 = ctx_r1.item().toggle) == null ? null : tmp_2_0.onChange == null ? null : tmp_2_0.onChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"]()(); } if (rf & 2) { let tmp_5_0; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("icon", ctx_r1.item().icon ?? "palette")("iconStyle", ctx_r1.item().iconStyle); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵclassMap"](ctx_r1.cn("p-menu-item-label grow text-sm", ctx_r1.item().labelClass)); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", ctx_r1.item().label, " "); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("ngModel", ((tmp_5_0 = ctx_r1.item().toggle) == null ? null : tmp_5_0.value) ?? false); } } function AnnotationMenuItemComponent_Case_3_Conditional_9_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "p-button", 16); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function AnnotationMenuItemComponent_Case_3_Conditional_9_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r7); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); const currentItem_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵreadContextLet"](0); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](currentItem_r6.slider.onReset()); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "lib-icon", 17); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpureFunction0"](1, _c0)); } } function AnnotationMenuItemComponent_Case_3_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](1, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function AnnotationMenuItemComponent_Case_3_Template_div_click_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](2, "span", 0); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](3, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](4, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](6, "div", 12)(7, "div", 13)(8, "p-slider", 14); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("ngModelChange", function AnnotationMenuItemComponent_Case_3_Template_p_slider_ngModelChange_8_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); const currentItem_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵreadContextLet"](0); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](currentItem_r6.slider == null ? null : currentItem_r6.slider.onSliderChange == null ? null : currentItem_r6.slider.onSliderChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](9, AnnotationMenuItemComponent_Case_3_Conditional_9_Template, 2, 2, "p-button", 15); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"]()()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); const currentItem_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵstoreLet"](ctx_r1.item()); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵclassMap"](currentItem_r8.styleClass); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("icon", currentItem_r8.icon ?? "palette")("iconStyle", currentItem_r8.iconStyle); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵclassMap"](ctx_r1.cn("p-menu-item-label text-sm", currentItem_r8.labelClass)); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", currentItem_r8.label, " "); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("min", currentItem_r8.slider.min ?? 0)("max", currentItem_r8.slider.max ?? 100)("step", currentItem_r8.slider.step ?? 1)("ngModel", currentItem_r8.slider.value); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](currentItem_r8.slider.showReset ? 9 : -1); } } function AnnotationMenuItemComponent_Case_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](0, "lib-menu-item", 3); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("item", ctx_r1.item()); } } class AnnotationMenuItemComponent { item = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "item" }] : [])); colors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_9__.ColorsService).pickerColors; fullColors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_9__.ColorsService).fullPickerColors; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.cn; static ɵfac = function AnnotationMenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationMenuItemComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵdefineComponent"]({ type: AnnotationMenuItemComponent, selectors: [["lib-annotation-menu-item"]], inputs: { item: [1, "item"] }, decls: 5, vars: 1, consts: [[1, "p-menu-item-link"], [1, "p-menu-item-link", "flex"], [3, "class"], [3, "item"], [3, "click"], ["width", "narrow", 3, "annotation", "colors"], [1, "p-menu-item-link", 3, "click"], ["iconClass", "p-menu-item-icon", 1, "size-3.5", 3, "icon", "iconStyle"], [3, "annotation", "colors"], [1, "p-menu-item-link", "flex", 3, "click"], ["iconClass", "p-menu-item-icon size-3.5", 3, "icon", "iconStyle"], [3, "ngModelChange", "ngModel"], [1, "px-4", "py-2"], [1, "flex", "w-full", "items-center", "gap-2"], ["data-test-id", "components-p-slider-slider", 1, "min-w-0", "flex-1", 3, "ngModelChange", "min", "max", "step", "ngModel"], ["data-test-id", "components-p-button-reset-slider", "variant", "text", "severity", "secondary", "rounded", "", 1, "ml-1", "opacity-70", "hover:opacity-100", 3, "pt"], ["data-test-id", "components-p-button-reset-slider", "variant", "text", "severity", "secondary", "rounded", "", 1, "ml-1", "opacity-70", "hover:opacity-100", 3, "click", "pt"], ["icon", "refresh", 1, "size-(--p-app-icon-size-xxs)"]], template: function AnnotationMenuItemComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](0, AnnotationMenuItemComponent_Case_0_Template, 2, 2, "div")(1, AnnotationMenuItemComponent_Case_1_Template, 3, 4, "span", 0)(2, AnnotationMenuItemComponent_Case_2_Template, 5, 6, "span", 1)(3, AnnotationMenuItemComponent_Case_3_Template, 10, 13, "div", 2)(4, AnnotationMenuItemComponent_Case_4_Template, 1, 1, "lib-menu-item", 3); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"]((tmp_0_0 = ctx.item().customType) === "color-swatch-full" ? 0 : tmp_0_0 === "color-swatch" ? 1 : tmp_0_0 === "toggle" ? 2 : tmp_0_0 === "slider" ? 3 : 4); } }, dependencies: [primeng_ripple__WEBPACK_IMPORTED_MODULE_4__.RippleModule, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.IconComponent, _color_swatch_menu_item_color_swatch_menu_item_component__WEBPACK_IMPORTED_MODULE_10__.ColorSwatchMenuItemComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.MenuItemComponent, primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_6__.ToggleSwitchModule, primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_6__.ToggleSwitch, primeng_slider__WEBPACK_IMPORTED_MODULE_5__.SliderModule, primeng_slider__WEBPACK_IMPORTED_MODULE_5__.Slider, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgModel, primeng_button__WEBPACK_IMPORTED_MODULE_3__.Button], encapsulation: 2 }); } /***/ }, /***/ 13609 /*!**************************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/components/annotation-menu.component.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationMenuComponent: () => (/* binding */ AnnotationMenuComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var _services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../services/submenu-flip/submenu-flip.service */ 9610); /* harmony import */ var _menu_tracker_service__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../menu-tracker.service */ 61487); /* harmony import */ var _annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./annotation-menu-item.component */ 45731); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["menu"]; function AnnotationMenuComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](0, "lib-annotation-menu-item", 3); } if (rf & 2) { const item_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("item", item_r2); } } class AnnotationMenuComponent { model = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)([], ...(ngDevMode ? [{ debugName: "model" }] : [])); appendTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('body', ...(ngDevMode ? [{ debugName: "appendTo" }] : [])); menu = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('menu'); tracker = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_menu_tracker_service__WEBPACK_IMPORTED_MODULE_4__.MenuTrackerService); submenuFlipService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_3__.SubmenuFlipService); menuPt = { root: { // Prevents being able to right-click an open menu and open the native menu oncontextmenu(event) { event.preventDefault(); } }, submenu: { class: 'min-w-0' } }; show(event) { const menu = this.menu(); menu.show(event); this.tracker.trackOpenMenu(menu); this.submenuFlipService.start(); } toggle(event) { const menu = this.menu(); const wasVisible = menu.visible(); menu.toggle(event); if (wasVisible) { this.submenuFlipService.stop(); } else { this.submenuFlipService.start(); } } onMenuHide() { this.submenuFlipService.stop(); } hide() { this.menu().hide(); } ngOnDestroy() { this.submenuFlipService.stop(); } static ɵfac = function AnnotationMenuComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationMenuComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: AnnotationMenuComponent, selectors: [["lib-annotation-menu"]], viewQuery: function AnnotationMenuComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵviewQuerySignal"](ctx.menu, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](); } }, inputs: { model: [1, "model"], appendTo: [1, "appendTo"] }, outputs: { model: "modelChange" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵProvidersFeature"]([{ provide: primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, useExisting: AnnotationMenuComponent }, _services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_3__.SubmenuFlipService])], decls: 4, vars: 3, consts: [["menu", ""], ["item", ""], ["popup", "", 3, "onHide", "pt", "model", "appendTo"], [3, "item"]], template: function AnnotationMenuComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "p-contextmenu", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("onHide", function AnnotationMenuComponent_Template_p_contextmenu_onHide_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onMenuHide()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplate"](2, AnnotationMenuComponent_ng_template_2_Template, 1, 1, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pt", ctx.menuPt)("model", ctx.model())("appendTo", ctx.appendTo()); } }, dependencies: [primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, _annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_5__.AnnotationMenuItemComponent], encapsulation: 2 }); } /***/ }, /***/ 75971 /*!********************************************************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/components/color-swatch-menu-item/color-swatch-menu-item.component.ts ***! \********************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ColorSwatchMenuItemComponent: () => (/* binding */ ColorSwatchMenuItemComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); function ColorSwatchMenuItemComponent_For_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdomElementStart"](0, "span", 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdomListener"]("click", function ColorSwatchMenuItemComponent_For_2_Template_span_click_0_listener() { const color_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.changeColor(color_r2)); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdomElementEnd"](); } if (rf & 2) { const color_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵclassMap"]("block h-7 w-7"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵstyleProp"]("background-color", color_r2); } } function isSCurve(item) { return item.type === 'control-point' || item.type === 'spline'; } class ColorSwatchMenuItemComponent { annotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "annotation" }] : [])); width = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('wide', ...(ngDevMode ? [{ debugName: "width" }] : [])); wide = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.width() === 'wide', ...(ngDevMode ? [{ debugName: "wide" }] : [])); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.AnnotationFacade); sCurveFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.SCurveFacade); colors = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "colors" }] : [])); changeColor(color) { const item = this.annotation(); if (!item) return; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.sCurveIsRelativeMeasurement)(item)) { this.sCurveFacade.updateRelativeMeasurement({ color, id: item.id }); } else if (isSCurve(item)) { this.sCurveFacade.updateSCurve((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_5__.changeColor)(item, color)); } else { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_5__.changeColor)(item, color)); } } static ɵfac = function ColorSwatchMenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ColorSwatchMenuItemComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: ColorSwatchMenuItemComponent, selectors: [["lib-color-swatch-menu-item"]], inputs: { annotation: [1, "annotation"], width: [1, "width"], colors: [1, "colors"] }, decls: 3, vars: 2, consts: [[3, "class", "background-color"], [3, "click"]], template: function ColorSwatchMenuItemComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdomElementStart"](0, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵrepeaterCreate"](1, ColorSwatchMenuItemComponent_For_2_Template, 1, 4, "span", 0, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵclassMap"](`flex ${ctx.wide() ? "w-56" : "w-35"} flex-wrap overflow-clip rounded-md`); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵrepeater"](ctx.colors()); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 12564 /*!**********************************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/directives/annotation-menu-trigger.directive.ts ***! \**********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationMenuTriggerDirective: () => (/* binding */ AnnotationMenuTriggerDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); class AnnotationMenuTriggerDirective { libMenuTrigger = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "libMenuTrigger" }] : [])); libMenuActions = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "libMenuActions" }] : [])); onClick(event) { const menu = this.libMenuTrigger(); const actions = this.libMenuActions(); if (menu && actions.length > 0) { event.stopPropagation(); event.preventDefault(); menu.model.set(actions); menu.toggle(event); } } static ɵfac = function AnnotationMenuTriggerDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationMenuTriggerDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ type: AnnotationMenuTriggerDirective, selectors: [["", "libMenuTrigger", ""]], hostBindings: function AnnotationMenuTriggerDirective_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("click", function AnnotationMenuTriggerDirective_click_HostBindingHandler($event) { return ctx.onClick($event); }); } }, inputs: { libMenuTrigger: [1, "libMenuTrigger"], libMenuActions: [1, "libMenuActions"] } }); } /***/ }, /***/ 61487 /*!**********************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/menu-tracker.service.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MenuTrackerService: () => (/* binding */ MenuTrackerService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); class MenuTrackerService { openMenus = []; trackOpenMenu(menu) { this.openMenus.push(menu); } closeTopMenu() { const menu = this.openMenus.pop(); if (menu) { menu.hide(); return true; } return false; } static ɵfac = function MenuTrackerService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MenuTrackerService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: MenuTrackerService, factory: MenuTrackerService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 27113 /*!************************************************************************!*\ !*** ./libs/feature/src/lib/annotation-menu/model-geometry.service.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ModelGeometryService: () => (/* binding */ ModelGeometryService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); class ModelGeometryService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_2__.AnnotationFacade); geometryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_2__.Object3DGeometryFacade); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_2__.viewportStore); /** Snap an object's orientation to a viewport view, keeping its own axial spin. */ alignWithViewport(annotation, axis) { const view = this.viewportStore.viewportAngulations()[axis]; const { ax } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.angulationFromOrientation)(annotation.orientation); this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setOrientation)(annotation, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.orientationFromAngulation)({ ax, cc: view.cc, rl: view.rl }))); } /** * Snap an object onto a closed spline: orient it en-face to the spline's * best-fit plane and move it to the spline's centroid. */ alignWithSpline(annotation, spline) { const normal = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getSplineBestFitNormal)(spline); const { cc, rl } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.vectorToAngulation)([normal[0], normal[1], normal[2]]); const { ax } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.angulationFromOrientation)(annotation.orientation); this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.move)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setOrientation)(annotation, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.orientationFromAngulation)({ ax, cc, rl })), (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getSplineCentroid)(spline))); } /** Flip the mesh 180 deg about its symmetry axis. */ flipAxis(stl) { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setAxisOfSymmetryRotation)(stl, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.flipAxisOfSymmetry)(stl.axisOfSymmetryRotation))); } setAxisOfSymmetry(stl) { const object = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.angulationFromOrientation)(stl.orientation); const view = this.viewportStore.primaryViewportAngulations(); const axisOfSymmetryRotation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.alignAxisOfSymmetryToView)(stl.axisOfSymmetryRotation, object, view); const orientation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.orientationFromAngulation)({ ax: object.ax, cc: view.cc, rl: view.rl }); this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setOrientation)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setAxisOfSymmetryRotation)(stl, axisOfSymmetryRotation), orientation)); } /** Move the mesh's pivot to its centroid. */ setCenterOfRotationToCentroid(stl) { const geometry = this.geometryFacade.getGeometry(stl.id); if (!geometry) return; const { centroid } = geometry; this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setCenterOfRotation)(stl, [centroid[0], centroid[1], centroid[2]])); } /** Clear the mesh's orientation back to identity. */ resetOrientation(stl) { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.resetOrientation)(stl)); } /** Recompute the PCA alignment and reset orientation to identity. */ resetSymmetry(stl) { const geometry = this.geometryFacade.getGeometry(stl.id); if (!geometry) return; const { rotationMatrix } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.autoAlignAxis)(geometry.vertices, geometry.centroid); this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.resetOrientation)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_3__.setAxisOfSymmetryRotation)(stl, rotationMatrix))); } static ɵfac = function ModelGeometryService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ModelGeometryService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ModelGeometryService, factory: ModelGeometryService.ɵfac }); } /***/ }, /***/ 35946 /*!*************************************************************!*\ !*** ./libs/feature/src/lib/card-theme/card-interaction.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isInteractiveCardDescendant: () => (/* binding */ isInteractiveCardDescendant) /* harmony export */ }); /** * True when a double-click on a card's outer wrapper originated from an interactive descendant * (a button, input, link, or anything marked data-propagate-click) rather than the card's own * background/content. Those elements handle their own double-click semantics (e.g. double-clicking * a rename input to select its text) and shouldn't also trigger the card's goTo action. * * Deliberately excludes [role="button"]: p-accordion-header sets role="button" on its own host * element (for its unrelated expand/collapse toggle), and that host wraps virtually the entire * card header - icon, name, every action button. Matching it here would flag almost every * double-click on the card as "interactive", breaking goTo entirely rather than narrowing it. * * `wrapper` bounds the search to the card's own subtree - without it, .closest() would keep * walking past the card into ancestors it doesn't control (e.g. a parent list item, router link, * or drag-drop container marked data-propagate-click for unrelated reasons), which would * incorrectly suppress goTo for a legitimate double-click on the card's own background. */ function isInteractiveCardDescendant(event, wrapper) { const target = event.target; const match = target?.closest('button, input, a, [data-propagate-click]'); return !!match && wrapper.contains(match); } /***/ }, /***/ 92147 /*!*******************************************************!*\ !*** ./libs/feature/src/lib/card-theme/card-theme.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CARD_BUTTON_STYLE: () => (/* binding */ CARD_BUTTON_STYLE), /* harmony export */ CARD_HOVER_CLASS: () => (/* binding */ CARD_HOVER_CLASS), /* harmony export */ DARK_CARD_THEME: () => (/* binding */ DARK_CARD_THEME), /* harmony export */ buildCardDt: () => (/* binding */ buildCardDt), /* harmony export */ buildCardPt: () => (/* binding */ buildCardPt) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const TOKEN_CARD = '{app.surface.card}'; const TOKEN_SURFACE_50 = '{surface.50}'; const TOKEN_SURFACE_300 = '{surface.300}'; const TOKEN_SURFACE_400 = '{surface.400}'; const TOKEN_SURFACE_500 = '{surface.500}'; const TOKEN_SURFACE_800 = '{surface.800}'; const CARD_HOVER_CLASS = 'group-hover:bg-(--p-app-surface-card-hover)! !transition-none'; // Header/rail button colors, shared by every card that // hosts p-button chrome inside its accordion panel. const CARD_BUTTON_STYLE = { '--p-button-outlined-secondary-border-color': 'transparent', '--p-button-outlined-secondary-color': 'var(--p-app-neutral-500)', '--p-button-text-secondary-color': 'var(--p-app-neutral-500)' }; // Shared palette for the selectable entity cards (annotation, s-curve). // The protocol cards keep their own state->token tables and use buildCardDt directly. const DARK_CARD_THEME = { default: { bg: TOKEN_CARD, bgHover: '{app.surface.card-hover}', hover: TOKEN_SURFACE_50, icon: TOKEN_SURFACE_500, mutedText: TOKEN_SURFACE_400, text: TOKEN_SURFACE_50 }, disabled: { bg: TOKEN_CARD, bgHover: TOKEN_CARD, hover: TOKEN_SURFACE_500, icon: TOKEN_SURFACE_500, mutedText: TOKEN_SURFACE_500, text: TOKEN_SURFACE_500 }, selected: { bg: TOKEN_SURFACE_800, bgHover: TOKEN_SURFACE_800, hover: TOKEN_SURFACE_50, icon: TOKEN_SURFACE_500, mutedText: TOKEN_SURFACE_300, text: TOKEN_SURFACE_50 } }; function buildCardDt(tokens) { const { bg, hover, icon, text } = tokens; const bgHover = tokens.bgHover ?? bg; const mutedText = tokens.mutedText ?? text; return { colorScheme: { dark: { content: { background: bg, color: text, mutedColor: mutedText }, header: { activeBackground: bg, activeColor: text, activeHoverBackground: bgHover, activeHoverColor: hover, background: bg, color: text, hoverBackground: bgHover, hoverColor: hover, toggleIcon: { activeColor: icon, activeHoverColor: icon, color: icon, hoverColor: icon } } }, // TODO: design. Stock Aura light placeholders, keep keys symmetric with `dark`. light: { content: { background: '{content.background}', color: '{text.color}', mutedColor: '{text.muted.color}' }, header: { activeBackground: '{content.background}', activeColor: '{text.color}', activeHoverBackground: '{content.background}', activeHoverColor: '{text.hover.color}', background: '{content.background}', color: '{text.color}', hoverBackground: '{content.background}', hoverColor: '{text.hover.color}', toggleIcon: { activeColor: '{text.muted.color}', activeHoverColor: '{text.color}', color: '{text.muted.color}', hoverColor: '{text.color}' } } } } }; } function buildCardPt(pt, state) { const hoverClass = state === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.CardState.DEFAULT ? CARD_HOVER_CLASS : ''; return { ...pt, content: { ...pt?.content, content: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.cn)('ml-5 mr-1 px-0', hoverClass, pt?.content?.content) }, header: { ...pt?.header, root: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.cn)('flex-row gap-3 rounded-none pr-1 justify-start min-h-[2.5rem]', hoverClass, pt?.header?.root), toggleicon: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.cn)('toggle-icon', pt?.header?.toggleicon) }, panel: { ...pt?.panel, root: { class: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.cn)('py-0 flex w-full border-none', hoverClass, pt?.panel?.root), style: { backgroundColor: 'var(--p-accordion-header-background)' } } }, wrapper: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.cn)(hoverClass, pt?.wrapper) }; } /***/ }, /***/ 69605 /*!*****************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-card/chamber-card.component.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberCardComponent: () => (/* binding */ ChamberCardComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _card_theme_card_interaction__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../../card-theme/card-interaction */ 35946); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../card-theme/card-theme */ 92147); /* harmony import */ var _chamber_menu_directives_chamber_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../chamber-menu/directives/chamber-menu-trigger.directive */ 65937); const _c0 = ["nameInput"]; const _c1 = ["nameLabel"]; const _c2 = ["suggestionsPopover"]; const _c3 = ["suggestionButton"]; const _c4 = () => ({ root: "size-6 shrink-0" }); const _c5 = () => ({ root: "py-1 px-0" }); const _c6 = () => ({ color: "var(--p-accordion-header-toggle-icon-color)" }); const _c7 = a0 => ({ secondary: a0 }); const _c8 = a0 => ({ outlined: a0 }); const _forTrack0 = ($index, $item) => $item.icon; function ChamberCardComponent_ng_container_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_Conditional_5_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](0, ChamberCardComponent_Conditional_5_ng_container_0_Template, 1, 0, "ng-container", 16); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const dragHandle_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](33); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", dragHandle_r2); } } function ChamberCardComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 27); } if (rf & 2) { const active_r3 = ctx.active; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("p-accordionheader-toggle-icon size-(--p-app-icon-size-xxs) text-(length:--p-app-icon-size-xxs)", !ctx_r3.cdkDrag() && "ml-2.5")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", active_r3 ? "chevron-down" : "chevron-right"); } } function ChamberCardComponent_ng_container_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_ng_container_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_Conditional_13_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](0, ChamberCardComponent_Conditional_13_ng_container_0_Template, 1, 0, "ng-container", 16); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const moreMenuBtn_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](39); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", moreMenuBtn_r5); } } function ChamberCardComponent_ng_container_15_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_ng_container_27_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0); } } function ChamberCardComponent_ng_template_28_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 28); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleProp"]("background-color", ctx_r3.selected() ? ctx_r3.accentColor() : ""); } } function ChamberCardComponent_ng_template_30_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](1, "lib-icon", 29); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("flex size-7 shrink-0 items-center justify-center rounded-full bg-(--p-app-surface-icon-holder)")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleProp"]("color", ctx_r3.chamber().color); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", "camera"); } } function ChamberCardComponent_ng_template_32_div_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 32); } } function ChamberCardComponent_ng_template_32_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 30); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](2, ChamberCardComponent_ng_template_32_div_2_Template, 1, 0, "div", 31); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("order-first size-3 px-1.5 py-3 text-(--p-accordion-header-toggle-icon-hover-color) opacity-0", ctx_r3.readOnly() ? "pointer-events-none" : "cursor-grab transition-opacity delay-100 group-hover:opacity-100 active:cursor-grabbing")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 3, "chamberCard.dragToReorder")); } } function ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 42); } } function ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 41); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("mousedown", function ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_Template_p_button_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.preventDefault()); })("click", function ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.clearChamberName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](3, ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_ng_template_3_Template, 1, 0, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 3, "common.clearName"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](2, 5, "common.clearName"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](7, _c4)); } } function ChamberCardComponent_ng_template_34_Conditional_1_For_9_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "li")(1, "button", 43, 11); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("mousedown", function ChamberCardComponent_ng_template_34_Conditional_1_For_9_Template_button_mousedown_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.preventDefault()); })("click", function ChamberCardComponent_ng_template_34_Conditional_1_For_9_Template_button_click_1_listener($event) { const suggestion_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); $event.stopPropagation(); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.selectNameSuggestion(suggestion_r9)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const suggestion_r9 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r3.clampedSuggestions().has(suggestion_r9) ? suggestion_r9 : undefined)("tooltipPosition", ctx_r3.clampedSuggestions().has(suggestion_r9) ? "left" : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", suggestion_r9, " "); } } function ChamberCardComponent_ng_template_34_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 34)(1, "div", 36)(2, "input", 37, 8); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_click_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keydown.space", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_keydown_space_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.handleSpace)($event)); })("keydown.enter", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_keydown_enter_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation()($event)); })("keyup.enter", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_keyup_enter_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.updateChamberName)($event)); })("keydown.escape", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_keydown_escape_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation()($event)); })("keyup.escape", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_keyup_escape_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.cancelEditChamberName)($event)); })("blur", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_blur_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.updateChamberName)($event)); })("input", function ChamberCardComponent_ng_template_34_Conditional_1_Template_input_input_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleEventPropagation(ctx_r3.refreshNameSuggestions)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](4, ChamberCardComponent_ng_template_34_Conditional_1_Conditional_4_Template, 5, 8, "p-button", 38); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](5, "p-popover", 39, 9)(7, "ul", 40); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](8, ChamberCardComponent_ng_template_34_Conditional_1_For_9_Template, 4, 3, "li", null, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("id", `chamber-${ctx_r3.chamber().id}-name`)("formControl", ctx_r3.chamberName); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("data-test-id", `chamber-card-input-${ctx_r3.chamber().id}-name`); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r3.chamberName.value ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("appendTo", "body")("dismissable", false); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](ctx_r3.filteredNameSuggestions()); } } function ChamberCardComponent_ng_template_34_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r10 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "button", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function ChamberCardComponent_ng_template_34_Conditional_2_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r10); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameClick($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](1, "span", 45, 12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx_r3.cn("min-w-0 flex-1 cursor-pointer text-left")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r3.isNameClamped() ? ctx_r3.chamber().name : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", ctx_r3.chamber().name, " "); } } function ChamberCardComponent_ng_template_34_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 33); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](1, ChamberCardComponent_ng_template_34_Conditional_1_Template, 10, 6, "div", 34)(2, ChamberCardComponent_ng_template_34_Conditional_2_Template, 4, 4, "button", 35); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r3.isEditing() ? 1 : 2); } } function ChamberCardComponent_ng_template_36_For_2_Conditional_0_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 49); } if (rf & 2) { const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", action_r12.icon)("pTooltip", action_r12.label); } } function ChamberCardComponent_ng_template_36_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r11 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 48); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function ChamberCardComponent_ng_template_36_For_2_Conditional_0_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"]().$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](action_r12.command == null ? null : action_r12.command($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](1, ChamberCardComponent_ng_template_36_For_2_Conditional_0_ng_template_1_Template, 1, 2, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ariaLabel", action_r12.label)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](3, _c5))("disabled", action_r12.disabled); } } function ChamberCardComponent_ng_template_36_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](0, ChamberCardComponent_ng_template_36_For_2_Conditional_0_Template, 3, 4, "p-button", 47); } if (rf & 2) { const action_r12 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](action_r12.icon ? 0 : -1); } } function ChamberCardComponent_ng_template_36_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 46); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](1, ChamberCardComponent_ng_template_36_For_2_Template, 1, 1, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](ctx_r3.cardActions()); } } function ChamberCardComponent_ng_template_38_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "lib-icon", 51); } } function ChamberCardComponent_ng_template_38_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "p-button", 50); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](2, ChamberCardComponent_ng_template_38_ng_template_2_Template, 1, 0, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const moreMenuTrigger_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](9, _c8, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](7, _c7, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](6, _c6))))("libChamberMenuTrigger", moreMenuTrigger_r13)("libMenuActions", ctx_r3.actions())("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 4, "common.moreActions")); } } class ChamberCardComponent { cdr = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.ChangeDetectorRef); chamber = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "chamber" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); actions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)([], ...(ngDevMode ? [{ debugName: "actions" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(true, { ...(ngDevMode ? { debugName: "selected" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); menuTrigger = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(...(ngDevMode ? [undefined, { debugName: "menuTrigger" }] : [])); readOnly = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(true, { ...(ngDevMode ? { debugName: "readOnly" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); clicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); goTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); updateName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); selectedChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); cdkDrag = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "cdkDrag" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); filteredNameSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "filteredNameSuggestions" }] : [])); clampedSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(new Set(), ...(ngDevMode ? [{ debugName: "clampedSuggestions" }] : [])); chamberName = new _angular_forms__WEBPACK_IMPORTED_MODULE_6__.FormControl(''); nameMaxLength = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.CHAMBER_NAME_MAX_LENGTH; nameInput = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameInput', ...(ngDevMode ? [{ debugName: "nameInput" }] : [])); isNameClamped = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isNameClamped" }] : [])); nameLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameLabel', ...(ngDevMode ? [{ debugName: "nameLabel" }] : [])); suggestionsPopover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('suggestionsPopover', ...(ngDevMode ? [{ debugName: "suggestionsPopover" }] : [])); suggestionButtons = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChildren)('suggestionButton', ...(ngDevMode ? [{ debugName: "suggestionButtons" }] : [])); isEditing = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isEditing" }] : [])); structureNameSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.CHAMBER_STRUCTURE_NAMES, ...(ngDevMode ? [{ debugName: "structureNameSuggestions" }] : [])); mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const pt = this.pt(); const hoverClass = this.getCardState() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DEFAULT ? _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_17__.CARD_HOVER_CLASS : ''; return { ...pt, content: { ...pt?.content, content: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn)('ml-5 mr-1 px-0', hoverClass, pt?.content?.content) }, header: { ...pt?.header, root: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn)('flex-row gap-3 rounded-none pr-1 justify-start min-h-[2.5rem]', hoverClass, pt?.header?.root), toggleicon: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn)('toggle-icon', pt?.header?.toggleicon) }, panel: { ...pt?.panel, root: { class: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn)('py-0 flex w-full border-none', hoverClass, pt?.panel?.root), style: { backgroundColor: 'var(--p-accordion-header-background)' } } }, wrapper: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn)(hoverClass, pt?.wrapper) }; }, ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); accentColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.chamber().hidden ? 'var(--p-text-muted-color)' : this.chamber().color, ...(ngDevMode ? [{ debugName: "accentColor" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_17__.buildCardDt)(_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_17__.DARK_CARD_THEME[this.getCardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); cardActions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.actions().filter(action => action.includeInCard), ...(ngDevMode ? [{ debugName: "cardActions" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_17__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cn; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.afterEveryRender)(() => { const element = this.nameLabel()?.nativeElement; if (!element) return; const clamped = element.scrollHeight > element.clientHeight; if (clamped !== this.isNameClamped()) this.isNameClamped.set(clamped); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.afterEveryRender)(() => { const clamped = new Set(this.suggestionButtons().filter(({ nativeElement }) => nativeElement.scrollWidth > nativeElement.clientWidth).map(({ nativeElement }) => nativeElement.textContent?.trim() ?? '')); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.isEqualSet)(clamped, this.clampedSuggestions())) this.clampedSuggestions.set(clamped); }); } ngOnInit() { this.chamberName.setValue(this.chamber().name); } contextMenu(event) { if (this.readOnly()) return; if (event.ctrlKey) { event.preventDefault(); this.clicked.emit(event); return; } const trigger = this.menuTrigger(); if (!trigger) return; trigger.model.set(this.actions()); trigger.toggle(event); } handleCardDoubleClick(event) { const wrapper = event.currentTarget; if (this.isEditing() || (0,_card_theme_card_interaction__WEBPACK_IMPORTED_MODULE_16__.isInteractiveCardDescendant)(event, wrapper)) return; this.goTo.emit(); } handleEventPropagation(callback) { return event => { event.stopPropagation(); event.preventDefault(); callback?.(); this.cdr.markForCheck(); }; } updateChamberName = () => { const value = this.chamberName.value ?? ''; if (value.trim().length === 0) { this.isEditing.set(false); return; } this.isEditing.set(false); this.updateName.emit(value); }; cancelEditChamberName = () => { this.isEditing.set(false); }; /** Clears the field's current text (without saving) so a new name can be picked from the * suggestions list with the mouse alone, no backspacing required. */ clearChamberName = () => { this.chamberName.setValue(''); this.refreshNameSuggestions(); this.nameInput()?.nativeElement.focus(); }; handleNameClick(event) { event.stopPropagation(); event.preventDefault(); if (this.readOnly() || this.isEditing()) return; this.chamberName.setValue(this.chamber().name); this.menuTrigger()?.hide(); this.isEditing.set(true); setTimeout(() => this.nameInput()?.nativeElement.focus()); this.cdr.markForCheck(); } refreshNameSuggestions = () => { const allNames = this.structureNameSuggestions(); if (allNames.length === 0) { this.filteredNameSuggestions.set([]); } else { const query = (this.chamberName.value ?? '').trim().toLowerCase(); this.filteredNameSuggestions.set(query ? allNames.filter(name => name.toLowerCase().includes(query)) : allNames); } this.syncSuggestionsPopover(); }; selectNameSuggestion(name) { this.chamberName.setValue(name.slice(0, this.nameMaxLength)); this.updateChamberName(); } syncSuggestionsPopover() { const input = this.nameInput()?.nativeElement; const popover = this.suggestionsPopover(); if (!popover || !input) return; if (this.filteredNameSuggestions().length > 0) { popover.show(undefined, input); } else { popover.hide(); } } handleSpace = () => { const value = this.chamberName.value ?? ''; if (value.length >= this.nameMaxLength) return; this.chamberName.setValue(value + ' '); }; getCardState() { if (this.selected()) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.SELECTED; return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DEFAULT; } angleLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const angulation = this.chamber().cameraOrientation; const posterior = this.chamber().isPosterior; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.formatAngulation)(angulation, posterior); }, ...(ngDevMode ? [{ debugName: "angleLabel" }] : [])); static ɵfac = function ChamberCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineComponent"]({ type: ChamberCardComponent, selectors: [["lib-chamber-card"]], viewQuery: function ChamberCardComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵviewQuerySignal"](ctx.nameInput, _c0, 5)(ctx.nameLabel, _c1, 5)(ctx.suggestionsPopover, _c2, 5)(ctx.suggestionButtons, _c3, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵqueryAdvance"](4); } }, inputs: { chamber: [1, "chamber"], pt: [1, "pt"], actions: [1, "actions"], selected: [1, "selected"], menuTrigger: [1, "menuTrigger"], readOnly: [1, "readOnly"], cdkDrag: [1, "cdkDrag"] }, outputs: { clicked: "clicked", goTo: "goTo", updateName: "updateName", selectedChange: "selectedChange" }, decls: 40, vars: 24, consts: [["panel", ""], ["toggleicon", ""], ["accentBar", ""], ["cardIcon", ""], ["dragHandle", ""], ["headerTitle", ""], ["contentActions", ""], ["moreMenuBtn", ""], ["nameInput", ""], ["suggestionsPopover", ""], ["icon", ""], ["suggestionButton", ""], ["nameLabel", ""], ["data-test-id", "chamber-card-div-wrapper", 3, "click", "dblclick", "contextmenu"], [1, "grow", 3, "pt", "dt", "value"], ["libCancelClick", "", 3, "pt"], [4, "ngTemplateOutlet"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-2", "py-1"], [1, "relative", 3, "pt"], [1, "flex", "gap-3"], [1, "flex", "grow", "flex-col", "gap-1", "py-1", "text-xs"], [1, "flex", "justify-between", "gap-1"], [1, "text-color", "ps-4"], [1, "flex", "items-center", "gap-1", "text-(--p-accordion-content-muted-color)"], [1, "min-w-5", "text-left", "whitespace-nowrap"], [1, "min-w-9.5", "text-right", "whitespace-nowrap"], ["data-propagate-click", "", 3, "icon"], [1, "absolute", "top-0", "left-0", "h-full", "w-1"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"], ["cdkDragHandle", "", "icon", "drag-handle"], ["class", "h-11 rounded-sm bg-(--p-app-dark-surface-base)", 4, "cdkDragPlaceholder"], [1, "h-11", "rounded-sm", "bg-(--p-app-dark-surface-base)"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], [1, "min-w-0", "flex-1"], ["type", "button", "data-test-id", "chamber-card-button-name-trigger", "data-propagate-click", "", 3, "class"], [1, "flex", "min-w-0", "items-center", "gap-1"], ["pInputText", "", "data-propagate-click", "", 1, "border-primary-400", "w-full", "min-w-0", "bg-transparent", "py-0.5", "text-sm", "text-inherit", 3, "click", "keydown.space", "keydown.enter", "keyup.enter", "keydown.escape", "keyup.escape", "blur", "input", "id", "formControl"], ["type", "button", "data-propagate-click", "", "data-test-id", "chamber-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "pTooltip", "ariaLabel", "pt"], ["data-propagate-click", "", 3, "appendTo", "dismissable"], ["data-propagate-click", "", "data-test-id", "chamber-card-ul-name-suggestions", 1, "max-h-48", "w-56", "overflow-auto", "text-sm"], ["type", "button", "data-propagate-click", "", "data-test-id", "chamber-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "mousedown", "click", "pTooltip", "ariaLabel", "pt"], ["icon", "times", 1, "size-3"], ["type", "button", "data-propagate-click", "", "data-test-id", "chamber-card-button-name-suggestion", 1, "hover:bg-surface-800", "block", "w-full", "overflow-hidden", "rounded", "px-2", "py-1", "text-left", "text-ellipsis", "whitespace-nowrap", "text-inherit", 3, "mousedown", "click", "pTooltip", "tooltipPosition"], ["type", "button", "data-test-id", "chamber-card-button-name-trigger", "data-propagate-click", "", 3, "click"], [1, "line-clamp-2", "wrap-anywhere", 3, "pTooltip"], [1, "-mt-2", "flex", "flex-col", "items-end"], ["data-test-id", "chamber-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "ariaLabel", "pt", "disabled"], ["data-test-id", "chamber-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "ariaLabel", "pt", "disabled"], ["tooltipPosition", "left", 1, "size-(--p-app-icon-size-xs)", 3, "icon", "pTooltip"], ["data-test-id", "chamber-card-p-button-more-actions", "data-propagate-click", "", "tooltipPosition", "left", "severity", "secondary", "outlined", "", "size", "small", 3, "dt", "libChamberMenuTrigger", "libMenuActions", "pTooltip"], ["icon", "ellipsis-v", 1, "size-(--p-app-icon-size-xxxs)", "text-(length:--p-app-icon-size-xxxs)"]], template: function ChamberCardComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function ChamberCardComponent_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.clicked.emit($event)); })("dblclick", function ChamberCardComponent_Template_div_dblclick_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.handleCardDoubleClick($event)); })("contextmenu", function ChamberCardComponent_Template_div_contextmenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.contextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](1, "p-accordion-panel", 14, 0)(3, "p-accordion-header", 15); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](4, ChamberCardComponent_ng_container_4_Template, 1, 0, "ng-container", 16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](5, ChamberCardComponent_Conditional_5_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](6, ChamberCardComponent_ng_template_6_Template, 1, 3, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](8, "div", 17)(9, "div", 18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](10, ChamberCardComponent_ng_container_10_Template, 1, 0, "ng-container", 16)(11, ChamberCardComponent_ng_container_11_Template, 1, 0, "ng-container", 16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](13, ChamberCardComponent_Conditional_13_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](14, "p-accordion-content", 19); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](15, ChamberCardComponent_ng_container_15_Template, 1, 0, "ng-container", 16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](16, "div", 20)(17, "div", 21)(18, "div", 22)(19, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](20); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](21, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](22, "div", 24)(23, "span", 25); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](25, "span", 26); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](26); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](27, ChamberCardComponent_ng_container_27_Template, 1, 0, "ng-container", 16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](28, ChamberCardComponent_ng_template_28_Template, 1, 2, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(30, ChamberCardComponent_ng_template_30_Template, 2, 5, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(32, ChamberCardComponent_ng_template_32_Template, 3, 5, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(34, ChamberCardComponent_ng_template_34_Template, 3, 1, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(36, ChamberCardComponent_ng_template_36_Template, 3, 0, "ng-template", null, 6, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"])(38, ChamberCardComponent_ng_template_38_Template, 4, 11, "ng-template", null, 7, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const accentBar_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](29); const cardIcon_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](31); const headerTitle_r16 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](35); const contentActions_r17 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](37); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx.cn("group flex w-full overflow-hidden", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", ctx.chamber().id); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r14); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx.cdkDrag() ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r15); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", headerTitle_r16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); const moreMenuTrigger_r18 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"](ctx.menuTrigger()); const moreActions_r19 = ctx.actions(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](!ctx.isEditing() && moreMenuTrigger_r18 && moreActions_r19.length ? 13 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pt", ctx.mergedPt().content); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r14); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](21, 22, "chamberCard.angulations"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate2"](" ", ctx.angleLabel().raoLao.direction, " ", ctx.angleLabel().raoLao.formattedValue, " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate2"](" ", ctx.angleLabel().caudCran.direction, " ", ctx.angleLabel().caudCran.formattedValue, " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", contentActions_r17); } }, dependencies: [_chamber_menu_directives_chamber_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_18__.ChamberMenuTriggerDirective, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionContent, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionPanel, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.CancelClickDirective, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragHandle, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragPlaceholder, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_14__.IconComponent, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.FormControlDirective, primeng_tooltip__WEBPACK_IMPORTED_MODULE_12__.Tooltip, primeng_popover__WEBPACK_IMPORTED_MODULE_11__.Popover, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputText, primeng_button__WEBPACK_IMPORTED_MODULE_9__.Button, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 44189 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-menu/chamber-menu-item.service.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberMenuItemService: () => (/* binding */ ChamberMenuItemService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const DESTRUCTIVE_CLASSES = 'text-(--p-app-status-danger)'; const trashIcon = 'trash'; class ChamberMenuItemService { translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.ChamberFacade); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore); confirmationService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_2__.ConfirmationService); selectedChamberIds = this.chamberFacade.selectedIds; menuItemsForChamber(chamber) { const renameLabels = { cancelLabel: this.translate.instant('common.cancel'), header: this.translate.instant('chamberMenu.renameHeader'), inputLabel: this.translate.instant('common.name'), saveLabel: this.translate.instant('common.save') }; const menuItems = [{ command: () => this.goToChamber(chamber), disabled: false, icon: 'target', includeInCard: true, label: this.translate.instant('chamberMenu.goToChamber', { name: chamber.name }) }, { // Preset names for a mouse-only rename with no dialog/typing, plus a trailing // "Custom…" entry that opens the popup dialog - consistent with how every other // submenu here works (the top-level row only opens the submenu, never its own action). icon: 'typography', items: [..._tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.CHAMBER_STRUCTURE_NAMES.map(name => ({ command: () => this.updateChamberName(chamber.id, name), label: name })), { separator: true }, { command: () => this.chamberFacade.openRenameDialog(chamber, renameLabels), label: this.translate.instant('chamberMenu.renameCustom') }], label: this.translate.instant('common.rename') }, { chamber, customType: 'color-swatch', icon: 'palette' }, { items: [{ chamber, customType: 'color-swatch-full' }], label: this.translate.instant('chamberMenu.otherColor') }]; const selectedIdCount = this.selectedChamberIds().length; if (selectedIdCount > 1) { menuItems.push({ command: event => this.confirmDeleteSelectedChambers(event.originalEvent?.target ?? undefined), icon: trashIcon, iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('chamberMenu.deleteSelectedChambers', { count: selectedIdCount }), linkClass: DESTRUCTIVE_CLASSES }); } else { menuItems.push({ command: event => this.confirmDeleteSingleChamber(chamber.id, event.originalEvent?.target ?? undefined), icon: trashIcon, iconClass: DESTRUCTIVE_CLASSES, label: this.translate.instant('chamberMenu.deleteChamber'), linkClass: DESTRUCTIVE_CLASSES }); } return menuItems; } goToChamber(chamber) { this.viewportStore.updateAngulations(chamber.cameraOrientation); this.viewportStore.rotateAX(chamber.ax); this.viewportStore.updatePosterior(chamber.isPosterior); // Crosshair rotation is derived from the matrix/ax/isPosterior above, so it must be // restored after they're set, not before. rotateCrosshair takes a relative delta (it // decreases the absolute rotation by whatever value is passed), not an absolute target, // so the exact delta needed to land on the stored value is computed here - otherwise the // result would depend on wherever the crosshair happened to be before this ran, and // repeated "go to chamber" presses would keep rotating it further each time. // // crosshairRotation/isocenter/intersection are undefined on chambers captured before // these fields existed - there's no real value to restore, so the current view is left // alone instead of snapping to a fabricated position. if (chamber.crosshairRotation !== undefined) { const activeAxis = this.viewportStore.viewportAxisMapping()[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportAxisState.MIDDLEMAIN]; const currentCrosshairRotation = this.viewportStore.viewportCrosshairRotations[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportAxisState.MIDDLEMAIN](); this.viewportStore.rotateCrosshair(activeAxis, currentCrosshairRotation - chamber.crosshairRotation); } // Isocenter/intersection (pan + slice position) - deliberately excludes zoom, so two // chambers can share the same angle but land on different slices. if (chamber.isocenter !== undefined) { this.viewportStore.updateIsoCenter(chamber.isocenter); } if (chamber.intersection !== undefined) { this.viewportStore.updateIntersection(chamber.intersection); } this.viewportStore.nudgeAngulationsToForceResettle(); } confirmDeleteSingleChamber(chamberId, target) { this.confirmDeletion([chamberId], 'single', target); } confirmDeleteSelectedChambers(target) { const selectedIds = this.selectedChamberIds(); if (selectedIds.length === 0) return; this.confirmDeletion(selectedIds, selectedIds.length > 1 ? 'selected' : 'single', target); } updateChamberName(chamberId, newName) { const chamber = this.chamberFacade.chamberMap()[chamberId]; if (chamber) { this.chamberFacade.updateChamber({ ...chamber, name: newName }); } } confirmDeletion(ids, mode, target) { const translationKeyByMode = { all: 'chamberMenu.confirmDeleteAll', selected: 'chamberMenu.confirmDeleteSelected', single: 'chamberMenu.confirmDeleteChamber' }; const translationKey = translationKeyByMode[mode]; this.confirmationService.confirm({ accept: () => this.chamberFacade.deleteChambers(ids), acceptButtonProps: { label: this.translate.instant(`${translationKey}.cta.accept`), severity: 'danger' }, acceptLabel: this.translate.instant(`${translationKey}.cta.accept`), header: this.translate.instant(`${translationKey}.title`), icon: 'exclamation-triangle', message: this.translate.instant(`${translationKey}.message`, { count: ids.length }), rejectButtonProps: { label: this.translate.instant('common.cancel'), outlined: true, severity: 'secondary' }, target: target ?? undefined }); } } /***/ }, /***/ 11612 /*!*********************************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-menu/components/chamber-menu-item.component.ts ***! \*********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberMenuItemComponent: () => (/* binding */ ChamberMenuItemComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_ripple__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/ripple */ 73271); /* harmony import */ var primeng_slider__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/slider */ 31486); /* harmony import */ var primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/toggleswitch */ 79945); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../colors/colors.service */ 39298); /* harmony import */ var _color_chamber_swatch_menu_item_color_chamber_swatch_menu_item_component__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./color-chamber-swatch-menu-item/color-chamber-swatch-menu-item.component */ 66969); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/core */ 14975); function ChamberMenuItemComponent_Case_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("click", function ChamberMenuItemComponent_Case_0_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](1, "lib-chamber-color-swatch-menu-item", 3); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("chamber", ctx_r1.item().chamber)("colors", ctx_r1.fullColors); } } function ChamberMenuItemComponent_Case_1_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("click", function ChamberMenuItemComponent_Case_1_Template_span_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](1, "lib-icon", 5)(2, "lib-chamber-color-swatch-menu-item", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("icon", ctx_r1.item().icon ?? "palette")("iconStyle", ctx_r1.item().iconStyle); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("chamber", ctx_r1.item().chamber)("colors", ctx_r1.colors); } } function ChamberMenuItemComponent_Case_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](0, "lib-menu-item", 1); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("item", ctx_r1.item()); } } class ChamberMenuItemComponent { item = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "item" }] : [])); colors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_8__.ColorsService).pickerColors; fullColors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_8__.ColorsService).fullPickerColors; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.cn; static ɵfac = function ChamberMenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberMenuItemComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdefineComponent"]({ type: ChamberMenuItemComponent, selectors: [["lib-chamber-menu-item"]], inputs: { item: [1, "item"] }, decls: 3, vars: 1, consts: [[1, "p-menu-item-link"], [3, "item"], [3, "click"], ["width", "narrow", 3, "chamber", "colors"], [1, "p-menu-item-link", 3, "click"], ["iconClass", "p-menu-item-icon", 1, "size-3.5", 3, "icon", "iconStyle"], [3, "chamber", "colors"]], template: function ChamberMenuItemComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditionalCreate"](0, ChamberMenuItemComponent_Case_0_Template, 2, 2, "div")(1, ChamberMenuItemComponent_Case_1_Template, 3, 4, "span", 0)(2, ChamberMenuItemComponent_Case_2_Template, 1, 1, "lib-menu-item", 1); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditional"]((tmp_0_0 = ctx.item().customType) === "color-swatch-full" ? 0 : tmp_0_0 === "color-swatch" ? 1 : 2); } }, dependencies: [primeng_ripple__WEBPACK_IMPORTED_MODULE_3__.RippleModule, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__.IconComponent, _color_chamber_swatch_menu_item_color_chamber_swatch_menu_item_component__WEBPACK_IMPORTED_MODULE_9__.ColorChamberSwatchMenuItemComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__.MenuItemComponent, primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_5__.ToggleSwitchModule, primeng_slider__WEBPACK_IMPORTED_MODULE_4__.SliderModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule], encapsulation: 2 }); } /***/ }, /***/ 23204 /*!****************************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-menu/components/chamber-menu.component.ts ***! \****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberMenuComponent: () => (/* binding */ ChamberMenuComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var _annotation_menu_menu_tracker_service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../annotation-menu/menu-tracker.service */ 61487); /* harmony import */ var _services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../services/submenu-flip/submenu-flip.service */ 9610); /* harmony import */ var _chamber_menu_item_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./chamber-menu-item.component */ 11612); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["menu"]; function ChamberMenuComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](0, "lib-chamber-menu-item", 3); } if (rf & 2) { const item_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("item", item_r2); } } class ChamberMenuComponent { model = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)([], ...(ngDevMode ? [{ debugName: "model" }] : [])); appendTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('body', ...(ngDevMode ? [{ debugName: "appendTo" }] : [])); menu = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('menu'); tracker = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_annotation_menu_menu_tracker_service__WEBPACK_IMPORTED_MODULE_3__.MenuTrackerService); submenuFlipService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_4__.SubmenuFlipService); menuPt = { root: { // Prevents being able to right-click an open menu and open the native menu oncontextmenu(event) { event.preventDefault(); } }, submenu: 'min-w-0' }; show(event) { const menu = this.menu(); menu.show(event); this.tracker.trackOpenMenu(menu); this.submenuFlipService.start(); } toggle(event) { const menu = this.menu(); const wasVisible = menu.visible(); menu.toggle(event); if (wasVisible) { this.submenuFlipService.stop(); } else { this.submenuFlipService.start(); } } onMenuHide() { this.submenuFlipService.stop(); } hide() { this.menu().hide(); } ngOnDestroy() { this.submenuFlipService.stop(); } static ɵfac = function ChamberMenuComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberMenuComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: ChamberMenuComponent, selectors: [["lib-chamber-menu"]], viewQuery: function ChamberMenuComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵviewQuerySignal"](ctx.menu, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](); } }, inputs: { model: [1, "model"], appendTo: [1, "appendTo"] }, outputs: { model: "modelChange" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵProvidersFeature"]([{ provide: primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, useExisting: ChamberMenuComponent }, _services_submenu_flip_submenu_flip_service__WEBPACK_IMPORTED_MODULE_4__.SubmenuFlipService])], decls: 4, vars: 3, consts: [["menu", ""], ["item", ""], ["popup", "", 3, "onHide", "pt", "model", "appendTo"], [3, "item"]], template: function ChamberMenuComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "p-contextmenu", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("onHide", function ChamberMenuComponent_Template_p_contextmenu_onHide_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onMenuHide()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplate"](2, ChamberMenuComponent_ng_template_2_Template, 1, 1, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pt", ctx.menuPt)("model", ctx.model())("appendTo", ctx.appendTo()); } }, dependencies: [primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, _chamber_menu_item_component__WEBPACK_IMPORTED_MODULE_5__.ChamberMenuItemComponent], encapsulation: 2 }); } /***/ }, /***/ 66969 /*!*****************************************************************************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-menu/components/color-chamber-swatch-menu-item/color-chamber-swatch-menu-item.component.ts ***! \*****************************************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ColorChamberSwatchMenuItemComponent: () => (/* binding */ ColorChamberSwatchMenuItemComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ color: a0 }); function ColorChamberSwatchMenuItemComponent_For_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdomElementStart"](0, "button", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdomListener"]("click", function ColorChamberSwatchMenuItemComponent_For_2_Template_button_click_0_listener() { const color_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.changeColor(color_r2)); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdomElementEnd"](); } if (rf & 2) { const color_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"]("block h-7 w-7 cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--p-primary-color)"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵstyleProp"]("background-color", color_r2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵattribute"]("data-test-id", "color-chamber-swatch-menu-item-button-" + color_r2)("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipeBind2"](1, 6, "chamberMenu.selectColor", _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpureFunction1"](9, _c0, color_r2))); } } class ColorChamberSwatchMenuItemComponent { chamber = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "chamber" }] : [])); width = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('wide', ...(ngDevMode ? [{ debugName: "width" }] : [])); wide = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.width() === 'wide', ...(ngDevMode ? [{ debugName: "wide" }] : [])); chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.ChamberFacade); colors = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "colors" }] : [])); changeColor(color) { const chamber = this.chamber(); if (chamber) { this.chamberFacade.updateChamber({ ...chamber, color }); } } static ɵfac = function ColorChamberSwatchMenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ColorChamberSwatchMenuItemComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: ColorChamberSwatchMenuItemComponent, selectors: [["lib-chamber-color-swatch-menu-item"]], inputs: { chamber: [1, "chamber"], width: [1, "width"], colors: [1, "colors"] }, decls: 3, vars: 2, consts: [["type", "button", 3, "class", "background-color"], ["type", "button", 3, "click"]], template: function ColorChamberSwatchMenuItemComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdomElementStart"](0, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrepeaterCreate"](1, ColorChamberSwatchMenuItemComponent_For_2_Template, 2, 11, "button", 0, _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"](`flex ${ctx.wide() ? "w-56" : "w-35"} flex-wrap overflow-clip rounded-md`); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrepeater"](ctx.colors()); } }, dependencies: [_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 65937 /*!************************************************************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber-menu/directives/chamber-menu-trigger.directive.ts ***! \************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberMenuTriggerDirective: () => (/* binding */ ChamberMenuTriggerDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); class ChamberMenuTriggerDirective { libChamberMenuTrigger = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "libChamberMenuTrigger" }] : [])); libMenuActions = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "libMenuActions" }] : [])); onClick(event) { const menu = this.libChamberMenuTrigger(); const actions = this.libMenuActions(); if (menu && actions.length > 0) { event.stopPropagation(); event.preventDefault(); menu.model.set(actions); menu.toggle(event); } } static ɵfac = function ChamberMenuTriggerDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberMenuTriggerDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ type: ChamberMenuTriggerDirective, selectors: [["", "libChamberMenuTrigger", ""]], hostBindings: function ChamberMenuTriggerDirective_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("click", function ChamberMenuTriggerDirective_click_HostBindingHandler($event) { return ctx.onClick($event); }); } }, inputs: { libChamberMenuTrigger: [1, "libChamberMenuTrigger"], libMenuActions: [1, "libMenuActions"] } }); } /***/ }, /***/ 16592 /*!*********************************************************!*\ !*** ./libs/feature/src/lib/chamber/chamber.service.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberService: () => (/* binding */ ChamberService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../colors/colors.service */ 39298); class ChamberService { chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.ChamberFacade); colorsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_5__.ColorsService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_2__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); createNewChamber({ angulation, ax, crosshairRotation, intersection, isocenter, isPosterior }) { const defaultNameTemplate = this.translate.instant('chamberMenu.defaultName', { index: '__INDEX__' }); const escapedDefaultNameTemplate = defaultNameTemplate.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); const indexPattern = String.raw`(\d+)`; const defaultNamePattern = new RegExp(`^${escapedDefaultNameTemplate.replace('__INDEX__', indexPattern)}$`); let maxIndex = 0; for (const { name } of this.chamberFacade.chambers()) { const match = defaultNamePattern.exec(name) ?? /^Chamber (\d+)$/.exec(name); if (match) { maxIndex = Math.max(maxIndex, Number(match[1])); } } const nextIndex = maxIndex + 1; const chamber = { ax, cameraOrientation: angulation, color: this.colorsService.currentColor(), crosshairRotation, hidden: false, id: (0,uuid__WEBPACK_IMPORTED_MODULE_3__["default"])(), intersection, isocenter, isPosterior: isPosterior, name: this.translate.instant('chamberMenu.defaultName', { index: nextIndex }) }; this.chamberFacade.addChamber(chamber); const createdChamber = this.chamberFacade.chambers().find(c => c.id === chamber.id); if (!createdChamber) { const errorMessage = this.translate.instant('chamberToastMessage.error', { name: chamber.name }); this.showToastMessage('error', errorMessage); return; } const successMessage = this.translate.instant('chamberToastMessage.success', { name: chamber.name }); this.showToastMessage('success', successMessage); this.colorsService.nextColor(); } showToastMessage(severity, summary) { this.messageService.add({ life: 3000, severity, summary }); } static ɵfac = function ChamberService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ChamberService, factory: ChamberService.ɵfac }); } /***/ }, /***/ 98063 /*!******************************************************!*\ !*** ./libs/feature/src/lib/colors/colors.config.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ COLORS_TOKEN: () => (/* binding */ COLORS_TOKEN), /* harmony export */ FULL_PICKER_COLORS_TOKEN: () => (/* binding */ FULL_PICKER_COLORS_TOKEN), /* harmony export */ PICKER_COLORS_TOKEN: () => (/* binding */ PICKER_COLORS_TOKEN), /* harmony export */ provideDefaultColors: () => (/* binding */ provideDefaultColors) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/ui */ 79048); // Color palettes can be overridden by providing different colors for these tokens. // The default values live in the Figma mirror (libs/ui/src/lib/theme/app-tokens.ts) // as the app.palette.* groups. const COLORS_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('Colors'); const PICKER_COLORS_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('PickerColors'); const FULL_PICKER_COLORS_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('FullPickerColors'); function provideDefaultColors() { return [ // The order that colors are chosen when creating annotations { provide: COLORS_TOKEN, useValue: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__.annotationPaletteHexColors }, // The order to display them in the color picker { provide: PICKER_COLORS_TOKEN, useValue: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__.pickerPaletteHexColors }, // The full-size color picker's colors { provide: FULL_PICKER_COLORS_TOKEN, useValue: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__.fullPickerPaletteHexColors }]; } /***/ }, /***/ 39298 /*!*******************************************************!*\ !*** ./libs/feature/src/lib/colors/colors.service.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ColorsService: () => (/* binding */ ColorsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _colors_config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./colors.config */ 98063); class ColorsService { colors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_config__WEBPACK_IMPORTED_MODULE_1__.COLORS_TOKEN); pickerColors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_config__WEBPACK_IMPORTED_MODULE_1__.PICKER_COLORS_TOKEN); fullPickerColors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_config__WEBPACK_IMPORTED_MODULE_1__.FULL_PICKER_COLORS_TOKEN); colorIndex = 0; constructor() { if (this.colors.length === 0) { throw new Error('COLORS_TOKEN must provide at least one color'); } } currentColor() { return this.colors[this.colorIndex]; } nextColor() { this.colorIndex++; if (this.colorIndex >= this.colors.length) { this.colorIndex = 0; } } static ɵfac = function ColorsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ColorsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ColorsService, factory: ColorsService.ɵfac }); } /***/ }, /***/ 7110 /*!*****************************************************************************************!*\ !*** ./libs/feature/src/lib/create-object3d-dialog/create-object3d-dialog.component.ts ***! \*****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CreateObject3DDialogComponent: () => (/* binding */ CreateObject3DDialogComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_checkbox__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/checkbox */ 10026); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_inputnumber__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/inputnumber */ 89567); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @angular/core */ 14975); function CreateObject3DDialogComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](3, "p-inputNumber", 8); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_1_Template_p_inputNumber_ngModelChange_3_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.diameter, $event) || (ctx_r1.diameter = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](4, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](7, "p-inputNumber", 9); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_1_Template_p_inputNumber_ngModelChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.height, $event) || (ctx_r1.height = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](2, 6, "createObject3d.diameter"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.diameter); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("min", 0.1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](6, 8, "createObject3d.height"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.height); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("min", 0.1); } } function CreateObject3DDialogComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](3, "p-inputNumber", 10); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_2_Template_p_inputNumber_ngModelChange_3_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.innerDiameter, $event) || (ctx_r1.innerDiameter = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](4, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](7, "p-inputNumber", 11); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_2_Template_p_inputNumber_ngModelChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.outerDiameter, $event) || (ctx_r1.outerDiameter = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](8, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](9); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](10, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](11, "p-inputNumber", 12); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_2_Template_p_inputNumber_ngModelChange_11_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.height, $event) || (ctx_r1.height = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](2, 9, "createObject3d.innerDiameter"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.innerDiameter); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("min", 0.1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](6, 11, "createObject3d.outerDiameter"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.outerDiameter); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("min", 0.1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](10, 13, "createObject3d.height"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.height); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("min", 0.1); } } function CreateObject3DDialogComponent_Conditional_3_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](0, "lib-icon", 15); } } function CreateObject3DDialogComponent_Conditional_3_ng_template_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](0, "lib-icon", 16); } } function CreateObject3DDialogComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 2)(1, "p-button", 13); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function CreateObject3DDialogComponent_Conditional_3_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.importStl("device")); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](3, CreateObject3DDialogComponent_Conditional_3_ng_template_3_Template, 1, 0, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](5, "p-button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function CreateObject3DDialogComponent_Conditional_3_Template_p_button_click_5_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.importStl("segmentation")); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](7, CreateObject3DDialogComponent_Conditional_3_ng_template_7_Template, 1, 0, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](2, 6, "createObject3d.device"))("loading", ctx_r1.loadingMode() === "device")("disabled", ctx_r1.loadingMode() !== undefined); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](6, 8, "createObject3d.segmentation"))("loading", ctx_r1.loadingMode() === "segmentation")("disabled", ctx_r1.loadingMode() !== undefined); } } function CreateObject3DDialogComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "label", 3)(1, "p-checkbox", 17); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function CreateObject3DDialogComponent_Conditional_4_Template_p_checkbox_ngModelChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r5); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r1.disableTranslationRotation, $event) || (ctx_r1.disableTranslationRotation = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.disableTranslationRotation); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("binary", true); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](3, 3, "createObject3d.disableTranslationRotation"), " "); } } function CreateObject3DDialogComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p-button", 18); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function CreateObject3DDialogComponent_Conditional_8_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.confirm()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](1, 1, "createObject3d.create")); } } class CreateObject3DDialogComponent { dialogReference = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_8__.DynamicDialogRef); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_5__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateService); object3DType = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "object3DType" }] : [])); diameter = 40; height = 30; innerDiameter = 40; outerDiameter = 44; /** * When enabled, the created object starts locked (interactive translation and * rotation disabled). */ disableTranslationRotation = false; /** STL import mode currently being parsed, or undefined when idle. */ loadingMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "loadingMode" }] : [])); cancel() { this.dialogReference.close(); } confirm() { this.dialogReference.close(this.buildConfig()); } buildConfig(options = {}) { const { stlData, stlImportMode } = options; return { diameter: this.diameter, height: this.height, innerDiameter: this.innerDiameter, locked: this.disableTranslationRotation, object3DType: this.object3DType(), outerDiameter: this.outerDiameter, stlData, stlImportMode }; } importStl(mode) { var _this = this; const input = document.createElement('input'); input.type = 'file'; input.accept = '.stl'; input.addEventListener('change', /*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const file = input.files?.[0]; if (!file) return; _this.loadingMode.set(mode); try { const { centroid, normals, vertices } = yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.parseSTL)(file); _this.dialogReference.close(_this.buildConfig({ stlData: { centroid, fileName: file.name, normals, vertices }, stlImportMode: mode })); } catch (error) { _this.loadingMode.set(undefined); _this.messageService.add({ detail: error.message, severity: 'error', sticky: true, summary: _this.translate.instant('createObject3d.stlParseError') }); } })); input.click(); } static ɵfac = function CreateObject3DDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CreateObject3DDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵdefineComponent"]({ type: CreateObject3DDialogComponent, selectors: [["lib-create-object3d-dialog"]], inputs: { object3DType: [1, "object3DType"] }, decls: 9, vars: 7, consts: [["icon", ""], [1, "flex", "flex-col", "gap-4", "px-4"], [1, "flex", "gap-4"], [1, "flex", "items-center", "gap-2"], [1, "flex", "justify-end", "gap-2"], ["severity", "secondary", "variant", "text", "data-test-id", "create-object3d-dialog-p-button-cancel", 3, "click", "label"], ["data-test-id", "create-object3d-dialog-p-button-confirm", 3, "label"], [1, "flex", "flex-col", "gap-1"], ["suffix", " mm", "data-test-id", "create-object3d-dialog-p-inputNumber-diameter", 3, "ngModelChange", "ngModel", "min"], ["suffix", " mm", "data-test-id", "create-object3d-dialog-p-inputNumber-height", 3, "ngModelChange", "ngModel", "min"], ["suffix", " mm", "data-test-id", "create-object3d-dialog-p-inputNumber-inner-diameter", 3, "ngModelChange", "ngModel", "min"], ["suffix", " mm", "data-test-id", "create-object3d-dialog-p-inputNumber-outer-diameter", 3, "ngModelChange", "ngModel", "min"], ["suffix", " mm", "data-test-id", "create-object3d-dialog-p-inputNumber-hollow-height", 3, "ngModelChange", "ngModel", "min"], ["fluid", "", "data-test-id", "create-object3d-dialog-p-button-device", 1, "flex-1", 3, "click", "label", "loading", "disabled"], ["fluid", "", "data-test-id", "create-object3d-dialog-p-button-segmentation", 1, "flex-1", 3, "click", "label", "loading", "disabled"], ["icon", "device", 1, "size-(--p-app-icon-size-md)"], ["icon", "segmentation", 1, "size-(--p-app-icon-size-md)"], ["data-test-id", "create-object3d-dialog-p-checkbox-disable-translation-rotation", 3, "ngModelChange", "ngModel", "binary"], ["data-test-id", "create-object3d-dialog-p-button-confirm", 3, "click", "label"]], template: function CreateObject3DDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](1, CreateObject3DDialogComponent_Conditional_1_Template, 8, 10); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](2, CreateObject3DDialogComponent_Conditional_2_Template, 12, 15); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](3, CreateObject3DDialogComponent_Conditional_3_Template, 9, 10, "div", 2)(4, CreateObject3DDialogComponent_Conditional_4_Template, 4, 5, "label", 3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](5, "div", 4)(6, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function CreateObject3DDialogComponent_Template_p_button_click_6_listener() { return ctx.cancel(); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](8, CreateObject3DDialogComponent_Conditional_8_Template, 2, 3, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.object3DType() === "cylinder" ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.object3DType() === "hollow_cylinder" ? 2 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.object3DType() === "stl_file" ? 3 : 4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](7, 5, "common.cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.object3DType() !== "stl_file" ? 8 : -1); } }, dependencies: [_angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgModel, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateModule, primeng_button__WEBPACK_IMPORTED_MODULE_6__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_6__.Button, primeng_checkbox__WEBPACK_IMPORTED_MODULE_7__.CheckboxModule, primeng_checkbox__WEBPACK_IMPORTED_MODULE_7__.Checkbox, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__.IconComponent, primeng_inputnumber__WEBPACK_IMPORTED_MODULE_9__.InputNumberModule, primeng_inputnumber__WEBPACK_IMPORTED_MODULE_9__.InputNumber, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 24340 /*!***************************************************************************************!*\ !*** ./libs/feature/src/lib/create-s-curve-dialog/create-s-curve-dialog.component.ts ***! \***************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CreateSCurveDialogComponent: () => (/* binding */ CreateSCurveDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ index: 1 }); const _c1 = () => ({ index: 2 }); function CreateSCurveDialogComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "fieldset", 1)(1, "legend", 2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](4, "lib-viewport-setting-slider", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("valueChange", function CreateSCurveDialogComponent_Conditional_9_Template_lib_viewport_setting_slider_valueChange_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx_r1.cc2, $event) || (ctx_r1.cc2 = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("resetClicked", function CreateSCurveDialogComponent_Conditional_9_Template_lib_viewport_setting_slider_resetClicked_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.cc2.set(0)); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](6, "lib-viewport-setting-slider", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("valueChange", function CreateSCurveDialogComponent_Conditional_9_Template_lib_viewport_setting_slider_valueChange_6_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx_r1.rl2, $event) || (ctx_r1.rl2 = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("resetClicked", function CreateSCurveDialogComponent_Conditional_9_Template_lib_viewport_setting_slider_resetClicked_6_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.rl2.set(ctx_r1.defaultRl2)); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind2"](3, 11, "createSCurve.onCurveView", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](18, _c1)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](5, 14, "createSCurve.cc"))("minValue", ctx_r1.angleMin)("maxValue", ctx_r1.angleMax)("showValue", true); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("value", ctx_r1.cc2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](7, 16, "createSCurve.rl"))("minValue", ctx_r1.angleMin)("maxValue", ctx_r1.angleMax)("showValue", true); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("value", ctx_r1.rl2); } } const ANGLE_MIN = -90; const ANGLE_MAX = 90; // A non-identical default second point, so the cross product used to derive // the two-point en-face angle is never a degenerate zero vector. const DEFAULT_RL2 = 45; class CreateSCurveDialogComponent { dialogReference = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DynamicDialogRef); pointCount = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "pointCount" }] : [])); // Pre-populates the sliders when reopening this dialog to edit an existing curve's views, // instead of the create flow's all-zero defaults. initialControlPoints = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "initialControlPoints" }] : [])); angleMin = ANGLE_MIN; angleMax = ANGLE_MAX; defaultRl2 = DEFAULT_RL2; cc1 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "cc1" }] : [])); rl1 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "rl1" }] : [])); cc2 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "cc2" }] : [])); rl2 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(DEFAULT_RL2, ...(ngDevMode ? [{ debugName: "rl2" }] : [])); ngOnInit() { const [point1, point2] = this.initialControlPoints() ?? []; if (point1) { this.rl1.set(point1[0]); this.cc1.set(point1[1]); } if (point2) { this.rl2.set(point2[0]); this.cc2.set(point2[1]); } } cancel() { this.dialogReference.close(); } confirm() { const point1 = [this.rl1(), this.cc1()]; const point2 = [this.rl2(), this.cc2()]; const controlPoints = this.pointCount() === 1 ? [point1] : [point1, point2]; this.dialogReference.close(controlPoints); } static ɵfac = function CreateSCurveDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CreateSCurveDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: CreateSCurveDialogComponent, selectors: [["lib-create-s-curve-dialog"]], inputs: { pointCount: [1, "pointCount"], initialControlPoints: [1, "initialControlPoints"] }, decls: 15, vars: 26, consts: [[1, "flex", "flex-col", "gap-4", "px-4"], [1, "flex", "flex-col", "gap-2"], [1, "mb-1", "text-sm", "font-medium"], [3, "valueChange", "resetClicked", "label", "minValue", "maxValue", "showValue", "value"], [1, "flex", "justify-end", "gap-2"], ["severity", "secondary", "variant", "text", "data-test-id", "create-s-curve-dialog-p-button-cancel", 3, "click", "label"], ["data-test-id", "create-s-curve-dialog-p-button-confirm", 3, "click", "label"]], template: function CreateSCurveDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 0)(1, "fieldset", 1)(2, "legend", 2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](5, "lib-viewport-setting-slider", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("valueChange", function CreateSCurveDialogComponent_Template_lib_viewport_setting_slider_valueChange_5_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx.cc1, $event) || (ctx.cc1 = $event); return $event; }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("resetClicked", function CreateSCurveDialogComponent_Template_lib_viewport_setting_slider_resetClicked_5_listener() { return ctx.cc1.set(0); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](7, "lib-viewport-setting-slider", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("valueChange", function CreateSCurveDialogComponent_Template_lib_viewport_setting_slider_valueChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx.rl1, $event) || (ctx.rl1 = $event); return $event; }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("resetClicked", function CreateSCurveDialogComponent_Template_lib_viewport_setting_slider_resetClicked_7_listener() { return ctx.rl1.set(0); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](9, CreateSCurveDialogComponent_Conditional_9_Template, 8, 19, "fieldset", 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](10, "div", 4)(11, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function CreateSCurveDialogComponent_Template_p_button_click_11_listener() { return ctx.cancel(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](13, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](14, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function CreateSCurveDialogComponent_Template_p_button_click_13_listener() { return ctx.confirm(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind2"](4, 14, "createSCurve.onCurveView", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](25, _c0)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](6, 17, "createSCurve.cc"))("minValue", ctx.angleMin)("maxValue", ctx.angleMax)("showValue", true); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("value", ctx.cc1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](8, 19, "createSCurve.rl"))("minValue", ctx.angleMin)("maxValue", ctx.angleMax)("showValue", true); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("value", ctx.rl1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx.pointCount() === 2 ? 9 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](12, 21, "common.cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](14, 23, "common.create")); } }, dependencies: [_ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateModule, primeng_button__WEBPACK_IMPORTED_MODULE_3__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_3__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_5__.ViewportSettingSliderComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 20619 /*!******************************************************************************************!*\ !*** ./libs/feature/src/lib/device-sizing-chart/device-sizing-chart-dialog.component.ts ***! \******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DeviceSizingChartDialogComponent: () => (/* binding */ DeviceSizingChartDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_iconfield__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/iconfield */ 60478); /* harmony import */ var primeng_inputicon__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/inputicon */ 73164); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_message__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/message */ 60134); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tag__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/tag */ 37587); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _device_sizing_chart_calculations__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./device-sizing-chart.calculations */ 31997); /* harmony import */ var _device_sizing_chart_data__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./device-sizing-chart.data */ 25235); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = (a0, a1) => ({ matched: a0, total: a1 }); const _c1 = a0 => ({ color: a0 }); function DeviceSizingChartDialogComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "p-message", 6); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](2, 1, "deviceSizingChart.empty.noClosedSplines"), " "); } } function DeviceSizingChartDialogComponent_Conditional_2_ng_template_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](1, "lib-icon", 22); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](2, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const spline_r3 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("icon", ctx_r1.closedSplineIcon)("iconStyle", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](3, _c1, spline_r3.color)); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](spline_r3.name); } } function DeviceSizingChartDialogComponent_Conditional_2_ng_template_16_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](1, "lib-icon", 22); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](2, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const spline_r4 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("icon", ctx_r1.closedSplineIcon)("iconStyle", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](3, _c1, spline_r4.color)); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](spline_r4.name); } } function DeviceSizingChartDialogComponent_Conditional_2_Conditional_35_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 18)(1, "p-button", 24); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("onClick", function DeviceSizingChartDialogComponent_Conditional_2_Conditional_35_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r5); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.filterText.set("")); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](2, 1, "deviceSizingChart.filter.clear")); } } function DeviceSizingChartDialogComponent_Conditional_2_ng_template_38_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "tr")(1, "th", 25); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](4, "p-sortIcon", 26); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](5, "th", 27); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](8, "p-sortIcon", 28); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](9, "th", 29); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](12, "p-sortIcon", 30); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](13, "th", 31); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](15, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](16, "th", 32); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](19, "p-sortIcon", 33); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](20, "th", 34); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](21); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](22, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](23, "p-sortIcon", 35); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](24, "th", 36); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](25); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](26, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](27, "p-sortIcon", 37); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](3, 7, "deviceSizingChart.table.columns.manufacturer"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](7, 9, "deviceSizingChart.table.columns.model"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](11, 11, "deviceSizingChart.table.columns.nominalSize"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](15, 13, "deviceSizingChart.table.columns.deployedSize"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](18, 15, "deviceSizingChart.table.columns.areaOversizing"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](22, 17, "deviceSizingChart.table.columns.perimeterOversizing"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](26, 19, "deviceSizingChart.table.columns.sizingCriteria"), " "); } } function DeviceSizingChartDialogComponent_Conditional_2_ng_template_40_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "tr")(1, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](3, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](5, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](7, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](9, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](11, "percent"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](12, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](13); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](14, "percent"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](15, "td")(16, "div", 38); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](17, "p-tag", 39); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](19, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](20, "div")(21, "span", 40); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](22); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](23, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()()()()(); } if (rf & 2) { const row_r6 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](row_r6.manufacturer); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](row_r6.model); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](row_r6.nominalSizeLabel); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](row_r6.deployedSizeLabel); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind2"](11, 12, row_r6.areaOversizing, "1.0-0")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind2"](14, 15, row_r6.perimeterOversizing, "1.0-0")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵclassMap"](row_r6.sizingMatch ? "border border-(--p-app-status-success)/40 px-3" : "border border-(--p-app-status-danger)/40 px-3"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("severity", row_r6.sizingMatch ? "success" : "danger")("value", row_r6.sizingMatch ? _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](18, 18, "deviceSizingChart.table.match") : _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](19, 20, "deviceSizingChart.table.noMatch")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate2"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](23, 22, row_r6.sizingParameterNameKey), ": ", row_r6.sizingParameterBounds, " "); } } function DeviceSizingChartDialogComponent_Conditional_2_ng_template_42_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "tr")(1, "td", 41)(2, "div", 42)(3, "div", 43); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](6, "p-button", 44); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("onClick", function DeviceSizingChartDialogComponent_Conditional_2_ng_template_42_Template_p_button_onClick_6_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.filterText.set("")); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](5, 3, "deviceSizingChart.empty.noDevices"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("outlined", true)("label", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](7, 5, "deviceSizingChart.filter.clearFilter")); } } function DeviceSizingChartDialogComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 7)(1, "label", 8)(2, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](5, "p-iconfield"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](6, "p-inputicon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](7, "input", 11); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("ngModelChange", function DeviceSizingChartDialogComponent_Conditional_2_Template_input_ngModelChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.filterText.set($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](9, "label", 8)(10, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](13, "p-select", 12); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("ngModelChange", function DeviceSizingChartDialogComponent_Conditional_2_Template_p_select_ngModelChange_13_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.selectedSpline.set($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](14, DeviceSizingChartDialogComponent_Conditional_2_ng_template_14_Template, 4, 5, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(16, DeviceSizingChartDialogComponent_Conditional_2_ng_template_16_Template, 4, 5, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](18, "div", 13)(19, "div", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](20); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](21, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](22, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](23); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](24, "div", 15); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](25, "\u00B7"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](26, "div", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](27); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](28, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](29, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](30); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](31, "div", 16)(32, "div", 17); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](33); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](34, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](35, DeviceSizingChartDialogComponent_Conditional_2_Conditional_35_Template, 3, 3, "div", 18); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](36, "div", 19)(37, "p-table", 20); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](38, DeviceSizingChartDialogComponent_Conditional_2_ng_template_38_Template, 28, 21, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(40, DeviceSizingChartDialogComponent_Conditional_2_ng_template_40_Template, 24, 24, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(42, DeviceSizingChartDialogComponent_Conditional_2_ng_template_42_Template, 8, 7, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](4, 15, "deviceSizingChart.filter.label"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngModel", ctx_r1.filterText())("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](8, 17, "deviceSizingChart.filter.placeholder")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](12, 19, "deviceSizingChart.spline.label"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngModel", ctx_r1.selectedSpline())("options", ctx_r1.closedSplines()); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](21, 21, "deviceSizingChart.measurements.area"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](ctx_r1.areaLabel()); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](28, 23, "deviceSizingChart.measurements.perimeter"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](ctx_r1.perimeterLabel()); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind2"](34, 25, "deviceSizingChart.matchCount", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction2"](28, _c0, ctx_r1.matchingDeviceCount(), ctx_r1.totalDeviceCount())), " "); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx_r1.filterText().trim() !== "" ? 35 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("value", ctx_r1.rows())("scrollable", true)("sortOrder", -1); } } class DeviceSizingChartDialogComponent { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_16__.AnnotationFacade); closedSplineIcon = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_17__.UiSvgIcon.CLOSEDSPLINE; initialSplineId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(...(ngDevMode ? [undefined, { debugName: "initialSplineId" }] : [])); filterText = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)('', ...(ngDevMode ? [{ debugName: "filterText" }] : [])); closedSplines = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.annotationFacade.annotations().filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_14__.annotationIsClosedSpline)(annotation)), ...(ngDevMode ? [{ debugName: "closedSplines" }] : [])); selectedSpline = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.linkedSignal)(() => { const splines = this.closedSplines(); return splines.find(({ id }) => id === this.initialSplineId()) ?? splines[0]; }, ...(ngDevMode ? [{ debugName: "selectedSpline" }] : [])); selectedMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const spline = this.selectedSpline(); if (!spline) return; return { area: (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_15__.getClosedSplineArea)(spline), perimeter: (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_15__.getSplineLength)(spline) }; }, ...(ngDevMode ? [{ debugName: "selectedMeasurements" }] : [])); rows = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const measurements = this.selectedMeasurements(); if (!measurements) return []; const terms = this.filterText().trim().toLowerCase().split(/\s+/).filter(Boolean); return _device_sizing_chart_data__WEBPACK_IMPORTED_MODULE_19__.TAVR_DEVICES.filter(device => this.deviceMatchesFilter(device, terms)).map(device => ({ areaOversizing: (0,_device_sizing_chart_calculations__WEBPACK_IMPORTED_MODULE_18__.oversizingArea)(device.deployedSize.value, measurements.area), deployedSizeLabel: this.sizeLabel(device.deployedSize.value, device.deployedSize.units), device, manufacturer: device.manufacturer, model: device.model, nominalSize: device.nominalSize.value, nominalSizeLabel: this.sizeLabel(device.nominalSize.value, device.nominalSize.units), perimeterOversizing: (0,_device_sizing_chart_calculations__WEBPACK_IMPORTED_MODULE_18__.oversizingPerimeter)(device.deployedSize.value, measurements.perimeter), sizingMatch: (0,_device_sizing_chart_calculations__WEBPACK_IMPORTED_MODULE_18__.sizingMatches)(device, measurements), sizingParameterBounds: `${device.sizingParameter.lowerBound} - ${device.sizingParameter.upperBound} ${device.sizingParameter.units}`, sizingParameterNameKey: `deviceSizingChart.parameters.${device.sizingParameter.name}` })); }, ...(ngDevMode ? [{ debugName: "rows" }] : [])); matchingDeviceCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.rows().filter(({ sizingMatch }) => sizingMatch).length, ...(ngDevMode ? [{ debugName: "matchingDeviceCount" }] : [])); totalDeviceCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.rows().length, ...(ngDevMode ? [{ debugName: "totalDeviceCount" }] : [])); areaLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const area = this.selectedMeasurements()?.area; return area === undefined ? '-' : `${this.formatNumber(area)} mm²`; }, ...(ngDevMode ? [{ debugName: "areaLabel" }] : [])); perimeterLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const perimeter = this.selectedMeasurements()?.perimeter; return perimeter === undefined ? '-' : `${this.formatNumber(perimeter)} mm`; }, ...(ngDevMode ? [{ debugName: "perimeterLabel" }] : [])); deviceMatchesFilter(device, terms) { if (terms.length === 0) return true; const name = `${device.manufacturer} ${device.model}`.toLowerCase(); return terms.every(term => name.includes(term)); } sizeLabel(value, units) { return `${value} ${units}`; } formatNumber(value) { return value.toFixed(1).replace('.0', ''); } static ɵfac = function DeviceSizingChartDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DeviceSizingChartDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵdefineComponent"]({ type: DeviceSizingChartDialogComponent, selectors: [["lib-device-sizing-chart-dialog"]], inputs: { initialSplineId: [1, "initialSplineId"] }, decls: 3, vars: 1, consts: [["selectedItem", ""], ["item", ""], ["header", ""], ["body", ""], ["emptymessage", ""], [1, "flex", "h-full", "min-h-0", "flex-col", "gap-4", "p-4"], ["severity", "secondary", "variant", "simple"], [1, "grid", "gap-3", "md:grid-cols-[minmax(16rem,24rem)_minmax(16rem,24rem)_auto_minmax(6rem,16rem)]", "md:items-end"], [1, "flex", "flex-col", "gap-1"], [1, "text-muted-color", "text-sm", "uppercase"], [1, "pi", "pi-search"], ["pInputText", "", "type", "text", "data-test-id", "device-sizing-chart-input-filter", 1, "w-full", 3, "ngModelChange", "ngModel", "placeholder"], ["appendTo", "body", "optionLabel", "name", "data-test-id", "device-sizing-chart-p-select-spline", 3, "ngModelChange", "ngModel", "options"], [1, "border-surface-200", "flex", "grow", "gap-2", "px-3", "py-2", "text-sm"], [1, "text-muted-color", "font-bold", "tracking-wide", "uppercase"], [1, "text-muted-color"], [1, "flex", "items-center", "justify-end", "gap-2"], [1, "text-muted-color", "py-3", "text-sm"], [1, "col-span-full", "flex", "justify-end"], [1, "min-h-0", "flex-1"], ["scrollHeight", "flex", "sortField", "sizingMatch", 1, "h-full", 3, "value", "scrollable", "sortOrder"], [1, "flex", "min-w-0", "items-center", "gap-2"], [1, "size-4", 3, "icon", "iconStyle"], [1, "min-w-0", "truncate"], ["severity", "secondary", "text", "", "data-test-id", "device-sizing-chart-p-button-clear-filter", 3, "onClick", "label"], ["pSortableColumn", "manufacturer"], ["field", "manufacturer"], ["pSortableColumn", "model"], ["field", "model"], ["pSortableColumn", "nominalSize", 1, "whitespace-nowrap"], ["field", "nominalSize"], [1, "whitespace-nowrap"], ["pSortableColumn", "areaOversizing", 1, "whitespace-nowrap"], ["field", "areaOversizing"], ["pSortableColumn", "perimeterOversizing", 1, "whitespace-nowrap"], ["field", "perimeterOversizing"], ["pSortableColumn", "sizingMatch", 1, "whitespace-nowrap"], ["field", "sizingMatch"], [1, "px-2"], [3, "severity", "value"], [1, "text-muted-color", "text-xs"], ["colspan", "7", 1, "h-full", "py-6"], [1, "flex", "h-full", "min-h-96", "flex-col", "items-center", "justify-center", "gap-3"], [1, "text-muted-color", "text-center"], ["severity", "secondary", "size", "small", "data-test-id", "device-sizing-chart-p-button-clear-filter", 3, "onClick", "outlined", "label"]], template: function DeviceSizingChartDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](1, DeviceSizingChartDialogComponent_Conditional_1_Template, 3, 3, "p-message", 6)(2, DeviceSizingChartDialogComponent_Conditional_2_Template, 44, 31); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx.closedSplines().length === 0 ? 1 : 2); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_6__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_6__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgModel, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_17__.IconComponent, primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__.InputText, primeng_iconfield__WEBPACK_IMPORTED_MODULE_7__.IconFieldModule, primeng_iconfield__WEBPACK_IMPORTED_MODULE_7__.IconField, primeng_inputicon__WEBPACK_IMPORTED_MODULE_8__.InputIconModule, primeng_inputicon__WEBPACK_IMPORTED_MODULE_8__.InputIcon, primeng_message__WEBPACK_IMPORTED_MODULE_10__.Message, primeng_select__WEBPACK_IMPORTED_MODULE_11__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_11__.Select, primeng_table__WEBPACK_IMPORTED_MODULE_12__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_12__.Table, primeng_table__WEBPACK_IMPORTED_MODULE_12__.SortableColumn, primeng_table__WEBPACK_IMPORTED_MODULE_12__.SortIcon, primeng_tag__WEBPACK_IMPORTED_MODULE_13__.Tag, _angular_common__WEBPACK_IMPORTED_MODULE_0__.PercentPipe, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 26755 /*!****************************************************************************************!*\ !*** ./libs/feature/src/lib/device-sizing-chart/device-sizing-chart-dialog.service.ts ***! \****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DeviceSizingChartDialogService: () => (/* binding */ DeviceSizingChartDialogService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _device_sizing_chart_dialog_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./device-sizing-chart-dialog.component */ 20619); class DeviceSizingChartDialogService { dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_2__.DialogService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); open(initialSplineId) { this.dialogService.open(_device_sizing_chart_dialog_component__WEBPACK_IMPORTED_MODULE_3__.DeviceSizingChartDialogComponent, { breakpoints: { '640px': '96vw', '960px': '90vw' }, closable: true, closeOnEscape: true, contentStyle: { height: '80vh', overflow: 'hidden' }, header: this.translate.instant('deviceSizingChart.title'), inputValues: { initialSplineId }, modal: true, width: '90vw' }); } static ɵfac = function DeviceSizingChartDialogService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DeviceSizingChartDialogService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: DeviceSizingChartDialogService, factory: DeviceSizingChartDialogService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 31997 /*!**************************************************************************************!*\ !*** ./libs/feature/src/lib/device-sizing-chart/device-sizing-chart.calculations.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ oversizingArea: () => (/* binding */ oversizingArea), /* harmony export */ oversizingPerimeter: () => (/* binding */ oversizingPerimeter), /* harmony export */ sizingMatches: () => (/* binding */ sizingMatches) /* harmony export */ }); function oversizingArea(deployedDiameter, splineArea) { const deviceArea = Math.PI * 0.25 * deployedDiameter * deployedDiameter; return (deviceArea - splineArea) / splineArea; } function oversizingPerimeter(deployedDiameter, splinePerimeter) { const devicePerimeter = Math.PI * deployedDiameter; return (devicePerimeter - splinePerimeter) / splinePerimeter; } function sizingMatches(device, measurements) { const sizingValue = device.sizingParameter.name === 'area' ? measurements.area : measurements.perimeter; const lowerMatches = device.sizingParameter.lowerBoundExclusive ? sizingValue > device.sizingParameter.lowerBound : sizingValue >= device.sizingParameter.lowerBound; const upperMatches = device.sizingParameter.upperBoundExclusive ? sizingValue < device.sizingParameter.upperBound : sizingValue <= device.sizingParameter.upperBound; return lowerMatches && upperMatches; } /***/ }, /***/ 25235 /*!******************************************************************************!*\ !*** ./libs/feature/src/lib/device-sizing-chart/device-sizing-chart.data.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TAVR_DEVICES: () => (/* binding */ TAVR_DEVICES) /* harmony export */ }); const TAVR_DEVICES = [device('Edwards', 'Sapien 3 Ultra', 20, 'area', 273, 345, 'mm²'), device('Edwards', 'Sapien 3 Ultra', 23, 'area', 338, 430, 'mm²'), device('Edwards', 'Sapien 3 Ultra', 26, 'area', 430, 546, 'mm²'), device('Edwards', 'Sapien 3 Ultra', 29, 'area', 540, 683, 'mm²'), device('Medtronic', 'Evolut R, Pro, Fx', 23, 'perimeter', 56.6, 62.8, 'mm'), device('Medtronic', 'Evolut R, Pro, Fx', 26, 'perimeter', 62.8, 72.3, 'mm'), device('Medtronic', 'Evolut R, Pro, Fx', 29, 'perimeter', 72.3, 81.7, 'mm'), device('Medtronic', 'Evolut R, Pro, Fx', 34, 'perimeter', 81.7, 94.2, 'mm'), device('Boston Scientific', 'ACURATE neo2 S', 23, 'perimeter', 66, 72, 'mm'), device('Boston Scientific', 'ACURATE neo2 M', 25, 'perimeter', 72, 79, 'mm'), device('Boston Scientific', 'ACURATE neo2 L', 27, 'perimeter', 79, 85, 'mm'), device('Boston Scientific', 'ACURATE Prime XL', 29, 'perimeter', 83, 91, 'mm'), device('Abbott', 'Navitor', 23, 'perimeter', 60, 66, 'mm'), device('Abbott', 'Navitor', 25, 'perimeter', 66, 73, 'mm'), device('Abbott', 'Navitor', 27, 'perimeter', 72, 79, 'mm'), device('Abbott', 'Navitor', 29, 'perimeter', 79, 85, 'mm'), device('Meril', 'Myval', 20, 'area', 270, 330, 'mm²'), device('Meril', 'Myval', 21.5, 'area', 314, 380, 'mm²'), device('Meril', 'Myval', 23, 'area', 360, 440, 'mm²'), device('Meril', 'Myval', 24.5, 'area', 410, 500, 'mm²'), device('Meril', 'Myval', 26, 'area', 460, 560, 'mm²'), device('Meril', 'Myval', 27.5, 'area', 510, 630, 'mm²'), device('Meril', 'Myval', 29, 'area', 570, 700, 'mm²'), device('Meril', 'Myval', 30.5, 'area', 630, 770, 'mm²'), device('Meril', 'Myval', 32, 'area', 700, 840, 'mm²'), device('JenaValve', 'Trilogy-THV-S', 23, 'perimeter', 66, 74, 'mm'), device('JenaValve', 'Trilogy-THV-M', 25, 'perimeter', 71, 79, 'mm'), device('JenaValve', 'Trilogy-THV-L', 27, 'perimeter', 76, 85, 'mm'), device('JenaValve', 'JenaValve', 23, 'perimeter', 66, 74, 'mm'), device('JenaValve', 'JenaValve', 25, 'perimeter', 71, 79, 'mm'), device('JenaValve', 'JenaValve', 27, 'perimeter', 76, 85, 'mm'), device('MicroPort', 'VitaFlow', 21, 'perimeter', 53.4, 62.8, 'mm'), device('MicroPort', 'VitaFlow', 24, 'perimeter', 62.8, 72.3, 'mm'), device('MicroPort', 'VitaFlow', 27, 'perimeter', 72.3, 81.7, 'mm'), device('MicroPort', 'VitaFlow', 30, 'perimeter', 81.7, 91.1, 'mm'), device('Biosensors International', 'ALLEGRA', 23, 'perimeter', 59.7, 69.1, 'mm'), device('Biosensors International', 'ALLEGRA', 27, 'perimeter', 69.1, 78.5, 'mm'), device('Biosensors International', 'ALLEGRA', 31, 'perimeter', 78.5, 88, 'mm'), device('Products & Features', 'Vienna', 23, 'perimeter', 53.4, 66, 'mm'), device('Products & Features', 'Vienna', 26, 'perimeter', 66, 72.3, 'mm'), device('Products & Features', 'Vienna', 29, 'perimeter', 72.3, 81.7, 'mm'), device('Products & Features', 'Vienna', 31, 'perimeter', 81.7, 91.1, 'mm')]; function device(manufacturer, model, diameter, parameterName, lowerBound, upperBound, units) { return { deployedSize: { name: 'diameter', units: 'mm', value: diameter }, manufacturer, model, nominalSize: { name: 'diameter', units: 'mm', value: diameter }, sizingParameter: { lowerBound, name: parameterName, units, upperBound } }; } /***/ }, /***/ 18809 /*!*****************************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/dicom-importer-dialog/dicom-importer-dialog.component.ts ***! \*****************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DICOM_IMPORTER_DIALOG_OPTIONS: () => (/* binding */ DICOM_IMPORTER_DIALOG_OPTIONS), /* harmony export */ DicomImporterDialogComponent: () => (/* binding */ DicomImporterDialogComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../logging/utils */ 14337); /* harmony import */ var _services_dicom_importer_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../services/dicom-importer.service */ 14043); /* harmony import */ var _patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../patient-library/patient-library-list.facade */ 67045); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["fileInput"]; const _c1 = a0 => ({ store: a0 }); function DicomImporterDialogComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "lib-heading-area", 8)(1, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](2, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](3, "div")(4, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](6, "div", 11)(7, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](10, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](11, "\u00B7"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](12, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](13); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](14, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementContainerStart"](15, 12); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](16, "div", 13)(17, "div", 14)(18, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](19); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](20, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](21, "div", 15); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](22, "div")(23, "div", 16)(24, "p-button", 17); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("click", function DicomImporterDialogComponent_Conditional_3_Template_p_button_click_24_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setViewMode("list")); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](25, "lib-icon", 18); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](26, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("click", function DicomImporterDialogComponent_Conditional_3_Template_p_button_click_26_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setViewMode("grid")); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](27, "lib-icon", 20); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementContainerEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵclassProp"]("blur-sm", ctx_r2.isImporting()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("showBackButton", false); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("icon", "folder-open"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", ctx_r2.importedFolderName(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate2"](" ", ctx_r2.patientCount(), " ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](9, 13, "dicomImporter.importDialog.heading.patients"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate2"](" ", ctx_r2.studyCount(), " ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](14, 15, "dicomImporter.importDialog.heading.studies"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate2"](" ", ctx_r2.seriesCount(), " ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](20, 17, "dicomImporter.importDialog.heading.series"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("severity", ctx_r2.viewMode() === "list" ? "primary" : "secondary"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("severity", ctx_r2.viewMode() === "grid" ? "primary" : "secondary"); } } function DicomImporterDialogComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("dragover", function DicomImporterDialogComponent_Conditional_5_Template_div_dragover_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.onDragOver($event)); })("dragleave", function DicomImporterDialogComponent_Conditional_5_Template_div_dragleave_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.onDragLeave($event)); })("drop", function DicomImporterDialogComponent_Conditional_5_Template_div_drop_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.onDrop($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](1, "div", 22); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](2, "lib-icon", 23); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](3, "div", 24)(4, "p", 25); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](7, "p", 26); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](10, "p-button", 27); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("click", function DicomImporterDialogComponent_Conditional_5_Template_p_button_click_10_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.importDicomFiles()); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵclassProp"]("ring-2", ctx_r2.isDragOver())("ring-primary", ctx_r2.isDragOver())("bg-surface-500", ctx_r2.isDragOver())("opacity-50", ctx_r2.isImporting() || ctx_r2.isClearingLocalImports())("pointer-events-none", ctx_r2.isImporting() || ctx_r2.isClearingLocalImports()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](6, 14, "dicomImporter.emptyState.title"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](9, 16, "dicomImporter.emptyState.subtitle"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("disabled", ctx_r2.isImporting() || ctx_r2.isClearingLocalImports()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](12, 18, "dicomImporter.emptyState.button"), " "); } } function DicomImporterDialogComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "div", 28)(1, "lib-table", 29); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtwoWayListener"]("selectedRowDataChange", function DicomImporterDialogComponent_Conditional_6_Template_lib_table_selectedRowDataChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtwoWayBindingSet"](ctx_r2.selectedImporterRows, $event) || (ctx_r2.selectedImporterRows = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵclassProp"]("blur-sm", ctx_r2.isImporting())("pointer-events-none", ctx_r2.isImporting()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("allowRowSelection", true)("columns", ctx_r2.columns)("rowData", ctx_r2.series()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtwoWayProperty"]("selectedRowData", ctx_r2.selectedImporterRows); } } function DicomImporterDialogComponent_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](0, "p-progressBar", 30); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](1, "span", 31); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](3, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](4, "%"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("showValue", false)("value", ctx_r2.totalProgress()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate"](ctx_r2.totalProgress()); } } function DicomImporterDialogComponent_Conditional_7_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "p-button", 32); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("click", function DicomImporterDialogComponent_Conditional_7_Conditional_2_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.clearAllLocalImports()); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](1, "lib-icon", 33); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](4, "p-button", 34); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("click", function DicomImporterDialogComponent_Conditional_7_Conditional_2_Template_p_button_click_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.bulkImportToLibrary()); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelement"](5, "lib-icon", 35); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("text", true)("disabled", ctx_r2.isImporting())("loading", ctx_r2.isClearingLocalImports()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind1"](3, 7, "dicomImporter.clearAllButton"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵproperty"]("disabled", ctx_r2.selectedImporterRows().length === 0 || ctx_r2.isImporting() || ctx_r2.dicomImporterService.isImportingToLibrary())("loading", ctx_r2.dicomImporterService.isImportingToLibrary()); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpipeBind2"](7, 9, ctx_r2.selectedStoreName() ? "dicomImporter.importToStoreButton" : "dicomImporter.importToLibraryButton", _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵpureFunction1"](12, _c1, ctx_r2.selectedStoreName())), " "); } } function DicomImporterDialogComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditionalCreate"](1, DicomImporterDialogComponent_Conditional_7_Conditional_1_Template, 5, 3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditionalCreate"](2, DicomImporterDialogComponent_Conditional_7_Conditional_2_Template, 8, 14); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditional"](ctx_r2.isImporting() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditional"](ctx_r2.series().length > 0 ? 2 : -1); } } const DICOM_IMPORTER_DIALOG_OPTIONS = { closable: true, draggable: false, height: '90vh', modal: true, pt: { root: 'p-2 px-4', title: 'text-3xl px-2' }, resizable: false, width: '80vw' }; class DicomImporterDialogComponent { fileInput; log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_10__.getLogger)(DicomImporterDialogComponent.name); dialogRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__.DynamicDialogRef, { optional: true }); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_4__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); isDragOver = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : [])); dicomImportService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_8__.DicomImportService); dicomImporterService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_dicom_importer_service__WEBPACK_IMPORTED_MODULE_11__["default"]); patientLibraryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_12__.PatientLibraryListFacade); selectedStoreUid = this.patientLibraryFacade.selectedStoreUid; selectedStoreName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.patientLibraryFacade.stores().find(store => store.uid === this.selectedStoreUid())?.name, ...(ngDevMode ? [{ debugName: "selectedStoreName" }] : [])); columns = [{ field: 'patientName', format: 'dicomPersonName' }, { field: 'patientID' }, { field: 'studyDate', format: 'dicomDate' }, { field: 'modality' }, { field: 'seriesDescription' }, { field: 'images' }, { field: 'studyDescription' }]; selectedImporterRows = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "selectedImporterRows" }] : [])); isClearingLocalImports = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "isClearingLocalImports" }] : [])); totalProgress = this.dicomImportService.totalProgress; // Signal-based rather than progress-based so the table stays in its loading // state until the last staged instance has been written to the local db. isImporting = this.dicomImportService.isImporting; viewMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)('list', ...(ngDevMode ? [{ debugName: "viewMode" }] : [])); clearedSeriesUids = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(new Set(), ...(ngDevMode ? [{ debugName: "clearedSeriesUids" }] : [])); series = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { return this.dicomImporterService.series().filter(row => !this.clearedSeriesUids().has(row.seriesInstanceUID)); }, ...(ngDevMode ? [{ debugName: "series" }] : [])); seriesCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.series().length, ...(ngDevMode ? [{ debugName: "seriesCount" }] : [])); studyCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => new Set(this.series().map(row => row.studyInstanceUID)).size, ...(ngDevMode ? [{ debugName: "studyCount" }] : [])); patientCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => new Set(this.series().map(row => row.patientID)).size, ...(ngDevMode ? [{ debugName: "patientCount" }] : [])); importedFolderName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "importedFolderName" }] : [])); knownSeriesUids = new Set(); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const stagedUids = new Set(this.dicomImporterService.series().map(row => row.seriesInstanceUID)); const cleared = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(this.clearedSeriesUids); if ([...cleared].some(uid => !stagedUids.has(uid))) { this.clearedSeriesUids.set(new Set([...cleared].filter(uid => stagedUids.has(uid)))); } }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const series = this.series(); const knownUids = this.knownSeriesUids; this.knownSeriesUids = new Set(series.map(row => row.seriesInstanceUID)); const selectedUids = new Set((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(this.selectedImporterRows).map(row => row.seriesInstanceUID)); this.selectedImporterRows.set(series.filter(row => selectedUids.has(row.seriesInstanceUID) || !knownUids.has(row.seriesInstanceUID))); }); } bulkImportToLibrary() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const selectedRows = _this.selectedImporterRows(); const uploadedSeriesUids = yield _this.dicomImporterService.importToLibrary(selectedRows); if (selectedRows.length === 0 || uploadedSeriesUids.length < selectedRows.length) return; _this.dialogRef?.close(); })(); } clearAllLocalImports() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const seriesUids = _this2.series().map(row => row.seriesInstanceUID); _this2.selectedImporterRows.set([]); _this2.clearedSeriesUids.set(new Set(seriesUids)); _this2.isClearingLocalImports.set(true); try { yield _this2.dicomImporterService.deleteStagedSeries(seriesUids); } catch (error) { _this2.clearedSeriesUids.set(new Set()); _this2.log.error('Failed to clear staged series', error); _this2.messageService.add({ life: 4000, severity: 'error', summary: _this2.translate.instant('dicomImporter.clearToast.error') }); } finally { _this2.isClearingLocalImports.set(false); } })(); } importDicomFiles() { if (!this.fileInput) { this.log.warn('file input not available'); return; } this.fileInput.nativeElement.value = ''; this.fileInput.nativeElement.click(); } onFilesSelected(event) { const input = event.target; if (!input.files || input.files.length === 0) { return; } const inputFiles = input.files; this.setFolderNameFromFiles(inputFiles); this.dicomImportService.onFilesSelected(inputFiles, this.selectedStoreUid()); } onDragOver(event) { if (this.isImporting() || this.isClearingLocalImports()) return; event.preventDefault(); this.isDragOver.set(true); } onDragLeave(event) { event.preventDefault(); this.isDragOver.set(false); } setViewMode(mode) { this.viewMode.set(mode); } onDrop(event) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { event.preventDefault(); _this3.isDragOver.set(false); if (_this3.isImporting() || _this3.isClearingLocalImports()) return; const items = event.dataTransfer?.items; if (!items) return; const files = yield _this3.collectFilesFromItems(items); if (files.length === 0) return; _this3.setFolderNameFromFiles(files); const dt = new DataTransfer(); for (const f of files) dt.items.add(f); _this3.dicomImportService.onFilesSelected(dt.files, _this3.selectedStoreUid()); })(); } collectFilesFromItems(items) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const files = []; const entries = Array.from({ length: items.length }, (_, index) => items[index]?.webkitGetAsEntry()).filter(entry => entry !== null); yield Promise.all(entries.map(entry => _this4.traverseEntry(entry, files))); return files; })(); } traverseEntry(entry, files) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (entry.isFile) { const file = yield new Promise((resolve, reject) => entry.file(resolve, reject)); files.push(file); } else if (entry.isDirectory) { const reader = entry.createReader(); const children = yield _this5.readAllEntries(reader); yield Promise.all(children.map(c => _this5.traverseEntry(c, files))); } else { // unsupported entry type, skip } })(); } setFolderNameFromFiles(files) { const fileArray = files instanceof FileList ? [...files] : files; const first = fileArray[0]; const relativePath = first?.webkitRelativePath; this.importedFolderName.set(relativePath?.split('/')[0] || undefined); } readAllEntries(reader) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const all = []; let batch; do { batch = yield new Promise((resolve, reject) => reader.readEntries(resolve, reject)); all.push(...batch); } while (batch.length > 0); return all; })(); } static ɵfac = function DicomImporterDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomImporterDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵdefineComponent"]({ type: DicomImporterDialogComponent, selectors: [["lib-dicom-importer-dialog"]], viewQuery: function DicomImporterDialogComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵviewQuery"](_c0, 5); } if (rf & 2) { let _t; _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵloadQuery"]()) && (ctx.fileInput = _t.first); } }, hostAttrs: [1, "flex", "h-full", "flex-col"], decls: 8, vars: 3, consts: [["fileInput", ""], [1, "bg-surface-900", "text-color", "flex", "h-full", "flex-col", "px-4"], ["data-test-id", "dicom-importer-dialog-input-files", "type", "file", "multiple", "", "webkitdirectory", "", "mozdirectory", "", "directory", "", 2, "display", "none", 3, "change"], [3, "showBackButton", "blur-sm"], [1, "relative", "min-h-0", "flex-1"], [1, "flex", "h-full", "items-center", "justify-center", "pt-8"], [1, "h-full", "overflow-auto", "transition-[filter]", 3, "blur-sm", "pointer-events-none"], [1, "flex", "shrink-0", "items-center", "justify-end", "gap-2", "py-4"], [3, "showBackButton"], ["left", "", 1, "flex", "items-center", "gap-2"], [1, "flex", "items-center", "justify-center", 3, "icon"], ["data-test-id", "dicom-importer-dialog-div-series-summary", 1, "text-muted-color", "mb-2", "flex", "shrink-0", "items-center", "gap-1", "text-sm"], ["right", ""], [1, "flex", "items-center", "gap-4"], ["data-test-id", "dicom-importer-dialog-div-series-summary", 1, "text-muted-color", "mb-2", "flex", "shrink-0", "items-center", "gap-2", "pt-2", "text-sm"], [1, "h-8", "w-px", "bg-(--p-app-surface-tab)"], [1, "flex", "gap-1", "rounded-md", "bg-(--p-app-neutral-950)", "p-1"], ["data-test-id", "dicom-importer-dialog-p-button-view-list", "severity", "secondary", "size", "large", "variant", "text", 3, "click", "severity"], ["icon", "list"], ["data-test-id", "dicom-importer-dialog-p-button-view-grid", "severity", "secondary", "size", "large", "variant", "text", 3, "click", "severity"], ["icon", "th-large"], [1, "flex", "h-full", "items-center", "justify-center", "pt-8", 3, "dragover", "dragleave", "drop"], [1, "keep-bg", "bg-surface-600", "flex", "flex-col", "items-center", "gap-5", "rounded-2xl", "px-24", "py-10", "text-center", "transition-all"], ["icon", "file-import", 1, "text-muted-color", "text-5xl"], [1, "flex", "flex-col", "gap-1"], [1, "text-color", "text-lg", "font-semibold"], [1, "text-muted-color", "text-sm"], ["data-test-id", "dicom-importer-dialog-p-button-choose-dicom-file", 3, "click", "disabled"], [1, "h-full", "overflow-auto", "transition-[filter]"], ["translationRoot", "dicomImporter", "rowKey", "seriesInstanceUID", 3, "selectedRowDataChange", "allowRowSelection", "columns", "rowData", "selectedRowData"], ["styleClass", "h-2 w-24", 3, "showValue", "value"], [1, "display-block", "w-8", "text-right"], ["data-test-id", "dicom-importer-dialog-p-button-clear-all", "severity", "danger", "size", "small", 3, "click", "text", "disabled", "loading"], ["icon", "trash"], ["data-test-id", "dicom-importer-dialog-p-button-import-to-store", "size", "small", "rounded", "", 3, "click", "disabled", "loading"], ["icon", "upload"]], template: function DicomImporterDialogComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](0, "div", 1)(1, "input", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵlistener"]("change", function DicomImporterDialogComponent_Template_input_change_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onFilesSelected($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditionalCreate"](3, DicomImporterDialogComponent_Conditional_3_Template, 28, 19, "lib-heading-area", 3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementStart"](4, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditionalCreate"](5, DicomImporterDialogComponent_Conditional_5_Template, 13, 20, "div", 5)(6, DicomImporterDialogComponent_Conditional_6_Template, 2, 8, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditionalCreate"](7, DicomImporterDialogComponent_Conditional_7_Template, 3, 2, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditional"](ctx.series().length !== 0 ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditional"](ctx.series().length === 0 ? 5 : 6); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_13__["ɵɵconditional"](ctx.series().length > 0 || ctx.isImporting() ? 7 : -1); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.TableComponent, primeng_button__WEBPACK_IMPORTED_MODULE_5__.Button, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__.ProgressBar, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.IconComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.HeadingAreaComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 26133 /*!*******************************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/export-to-store-dialog/export-to-store-dialog.component.ts ***! \*******************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ExportToStoreDialogComponent: () => (/* binding */ ExportToStoreDialogComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/progressspinner */ 7271); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../services/annotation-export-bridge.service */ 68674); /* harmony import */ var _services_dicom_export_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../services/dicom-export.service */ 8027); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ count: a0 }); function ExportToStoreDialogComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](1, "p-progressSpinner", 5); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](2, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](4, 1, "dicomImporter.exportToStoreDialog.exporting"), " "); } } function ExportToStoreDialogComponent_Conditional_2_Conditional_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](1, "p-progressSpinner", 13); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](4, 1, "dicomImporter.exportToStoreDialog.checkingStores")); } } function ExportToStoreDialogComponent_Conditional_2_Conditional_10_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-select", 14); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayListener"]("ngModelChange", function ExportToStoreDialogComponent_Conditional_2_Conditional_10_Template_p_select_ngModelChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayBindingSet"](ctx_r1.selectedStore, $event) || (ctx_r1.selectedStore = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("options", ctx_r1.stores()); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.selectedStore); } } function ExportToStoreDialogComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 7)(1, "label", 8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](4, "input", 9); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayListener"]("ngModelChange", function ExportToStoreDialogComponent_Conditional_2_Template_input_ngModelChange_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayBindingSet"](ctx_r1.analysisName, $event) || (ctx_r1.analysisName = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](5, "div", 7)(6, "label", 10); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](9, ExportToStoreDialogComponent_Conditional_2_Conditional_9_Template, 5, 3, "div", 11)(10, ExportToStoreDialogComponent_Conditional_2_Conditional_10_Template, 1, 2, "p-select", 12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](11, "p", 6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](13, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](3, 6, "dicomImporter.exportToStoreDialog.analysisNameLabel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtwoWayProperty"]("ngModel", ctx_r1.analysisName); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵattribute"]("maxlength", ctx_r1.analysisNameMaxLength); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](8, 8, "dicomImporter.exportToStoreDialog.storeLabel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx_r1.loadingStores() ? 9 : 10); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind2"](13, 10, "dicomImporter.exportToStoreDialog.description", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction1"](13, _c0, ctx_r1.seriesUids.length)), " "); } } /** Matches the `name` field limit in the work session schema (`workSessionSchema`). */ const ANALYSIS_NAME_MAX_LENGTH = 64; class ExportToStoreDialogComponent { ref = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__.DynamicDialogRef); config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__.DynamicDialogConfig); exportService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_13__.DicomExportService); exportBridge = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_12__.AnnotationExportBridge); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.DicomStoreListService); workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.WorkSessionDatabaseService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_4__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); state = this.exportService.state; stores = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "stores" }] : [])); loadingStores = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(true, ...(ngDevMode ? [{ debugName: "loadingStores" }] : [])); analysisNameMaxLength = ANALYSIS_NAME_MAX_LENGTH; selectedStore; /** Defaults to the current analysis name; editing it renames the analysis for this export only. */ analysisName = ''; get seriesUids() { return this.config.data?.seriesUids ?? []; } get storeUid() { return this.config.data?.storeUid ?? ''; } get studyUid() { return this.config.data?.studyUid ?? ''; } get workSessionUid() { return this.config.data?.workSessionUid ?? ''; } get existingOtSeriesUid() { return this.config.data?.existingOtSeriesUid; } ngOnInit() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this.analysisName = _this.exportBridge.workSessionName(); try { const stores = yield _this.storeList.getReachableStores(); _this.stores.set(stores); const defaultUid = _this.config.data?.defaultStoreUid; _this.selectedStore = defaultUid && stores.find(s => s.uid === defaultUid) || stores[0]; if (stores.length === 0) { yield _this.warnIfConfiguredStoresUnreachable(); } } finally { _this.loadingStores.set(false); } })(); } /** * Distinguishes "no DICOM stores configured" from "stores are configured but none * responded to a ping" — the latter warrants a toast since it usually means bad * credentials or an unreachable store instance. */ warnIfConfiguredStoresUnreachable() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const enabled = yield _this2.storeList.getEnabledStores(); if (enabled.length === 0) return; _this2.messageService.add({ detail: _this2.translate.instant('dicomImporter.storesUnreachable.detail'), life: 8000, severity: 'error', summary: _this2.translate.instant('dicomImporter.storesUnreachable.summary') }); })(); } onExport() { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const originalName = _this3.exportBridge.workSessionName(); const trimmedName = _this3.analysisName.trim(); const workSessionName = trimmedName || originalName; // The OT series identity is a deterministic function of (work session, name), so // repeat exports under the same name always land on the same series regardless of // whether the name change happened this call or a previous one — unless we're // updating a specific, already-known OT series, whose identity must stay put. const workSessionUID = _this3.existingOtSeriesUid ? _this3.workSessionUid : yield _this3.exportService.deriveRenamedWorkSessionUid(_this3.workSessionUid, workSessionName); yield _this3.exportService.exportSeriesToStore({ activePhaseInstanceUIDs: _this3.exportBridge.sourceInstanceUIDs(), annotations: _this3.exportBridge.annotations(), author: _this3.exportBridge.author, authorUserId: _this3.exportBridge.authorUserId, destinationStoreUid: _this3.selectedStore?.uid, existingOtSeriesUid: _this3.existingOtSeriesUid, phaseLabel: _this3.exportBridge.activePhaseLabel(), previewPixels: _this3.exportBridge.capturePreview?.(), protocolBindings: _this3.exportBridge.protocolBindings(), protocolFormValues: _this3.exportBridge.protocolFormValues(), renderSettings2D: _this3.exportBridge.renderSettings2D(), renderSettings3D: _this3.exportBridge.renderSettings3D(), seriesUids: _this3.seriesUids, sourceStudyUid: _this3.studyUid, storeUid: _this3.storeUid, workSessionName, workSessionUID }); // Only rename the local record once the store export has actually succeeded, // so a failed export doesn't leave the local name out of sync with the store. if (_this3.workSessionUid) { yield _this3.renameLocalWorkSessionIfPresent(_this3.workSessionUid, workSessionName); } _this3.ref.close({ messageKey: 'dicomImporter.exportToast.success', severity: 'success' }); } catch (error) { _this3.ref.close({ detail: error.message, messageKey: 'dicomImporter.exportToast.error', severity: 'error' }); } })(); } onCancel() { this.ref.close(); } /** Keeps the local analysis record's name in sync when it's already been saved to RxDB. */ renameLocalWorkSessionIfPresent(uid, name) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const existing = yield _this4.workSessionDb.get(uid); if (!existing || existing.name === name) return; const updated = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_10__.workSessionSchema.parse({ ...existing, name }); yield _this4.workSessionDb.save(updated, { incrementVersion: true }); })(); } static ɵfac = function ExportToStoreDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ExportToStoreDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵdefineComponent"]({ type: ExportToStoreDialogComponent, selectors: [["lib-export-to-store-dialog"]], features: [_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵProvidersFeature"]([_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_13__.DicomExportService])], decls: 10, vars: 9, consts: [[1, "flex", "flex-col", "gap-6", "p-4"], [1, "flex", "flex-col", "items-center", "gap-3", "py-4"], [1, "flex", "justify-end", "gap-2"], ["data-test-id", "export-to-store-dialog-p-button-cancel", "severity", "secondary", "outlined", "", 3, "click", "disabled"], ["data-test-id", "export-to-store-dialog-p-button-export", 3, "click", "disabled"], ["strokeWidth", "4", 1, "size-12"], [1, "text-muted-color", "text-sm"], [1, "flex", "flex-col", "gap-2"], ["for", "export-to-store-dialog-analysis-name", 1, "text-muted-color", "text-sm", "font-medium"], ["id", "export-to-store-dialog-analysis-name", "data-test-id", "export-to-store-dialog-input-analysis-name", "pInputText", "", 1, "w-full", 3, "ngModelChange", "ngModel"], [1, "text-muted-color", "text-sm", "font-medium"], [1, "text-muted-color", "flex", "w-full", "items-center", "justify-center", "gap-2", "text-sm"], ["data-test-id", "export-to-store-dialog-p-select-store", "optionLabel", "name", 1, "w-full", 3, "options", "ngModel"], ["strokeWidth", "4", 1, "size-4"], ["data-test-id", "export-to-store-dialog-p-select-store", "optionLabel", "name", 1, "w-full", 3, "ngModelChange", "options", "ngModel"]], template: function ExportToStoreDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](1, ExportToStoreDialogComponent_Conditional_1_Template, 5, 3, "div", 1)(2, ExportToStoreDialogComponent_Conditional_2_Template, 14, 15); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "div", 2)(4, "p-button", 3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("click", function ExportToStoreDialogComponent_Template_p_button_click_4_listener() { return ctx.onCancel(); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](7, "p-button", 4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("click", function ExportToStoreDialogComponent_Template_p_button_click_7_listener() { return ctx.onExport(); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx.state() === "exporting" ? 1 : 2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("disabled", ctx.state() === "exporting"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](6, 5, "dicomImporter.exportToStoreDialog.cancel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("disabled", !ctx.selectedStore || ctx.stores().length === 0 || ctx.state() === "exporting" || ctx.loadingStores()); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](9, 7, "dicomImporter.exportToStoreDialog.export"), " "); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_5__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_5__.Button, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateModule, primeng_select__WEBPACK_IMPORTED_MODULE_9__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_9__.Select, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgModel, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__.ProgressSpinnerModule, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__.ProgressSpinner, primeng_inputtext__WEBPACK_IMPORTED_MODULE_7__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_7__.InputText, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 89442 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/instance-picker.component.ts ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ InstancePickerComponent: () => (/* binding */ InstancePickerComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../review-status-icon/review-status-icon.component */ 92729); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/api */ 62751); const _c0 = ["popover"]; const _c1 = () => ({ background: "{surface.800}", borderColor: "{primary.500}", color: "{surface.50}" }); const _c2 = a0 => ({ root: a0 }); const _c3 = () => ({ borderColor: "{surface.700}" }); const _c4 = () => ({ background: "{surface.800}", borderColor: "{surface.700}", color: "{surface.50}" }); const _c5 = () => ({ background: "{surface.800}", color: "{surface.50}", hoverBackground: "{surface.700}" }); const _c6 = (a0, a1, a2) => ({ bodyCell: a0, headerCell: a1, row: a2 }); function InstancePickerComponent_ng_template_3_Conditional_12_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](0, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](2, 1, "patientDetails.instancePicker.phase")); } } function InstancePickerComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](0, "tr")(1, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](2, "#"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](3, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](6, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](9, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditionalCreate"](12, InstancePickerComponent_ng_template_3_Conditional_12_Template, 3, 3, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](13, "th", 5); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](14); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](15, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](16, "th", 5); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelement"](19, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](5, 6, "patientDetails.instancePicker.date")); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](8, 8, "patientDetails.instancePicker.time")); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](11, 10, "patientDetails.instancePicker.annotator")); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditional"](ctx_r0.hasPhaseLabels() ? 12 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](15, 12, "patientDetails.instancePicker.reviewed")); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](18, 14, "patientDetails.instancePicker.local")); } } function InstancePickerComponent_ng_template_4_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](0, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵnextContext"](); const item_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](item_r3.phaseLabel || "\u2014"); } } function InstancePickerComponent_ng_template_4_Conditional_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](0, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelement"](1, "lib-icon", 9); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](2, 1, "patientDetails.cachedLocally")); } } function InstancePickerComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](1, "tr")(2, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](4, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](6, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](8, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](9); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditionalCreate"](10, InstancePickerComponent_ng_template_4_Conditional_10_Template, 2, 1, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](11, "td", 5); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelement"](12, "lib-review-status-icon", 6); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](13, "td", 5); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditionalCreate"](14, InstancePickerComponent_ng_template_4_Conditional_14_Template, 3, 3, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](15, "td")(16, "p-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵlistener"]("click", function InstancePickerComponent_ng_template_4_Template_p_button_click_16_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrestoreView"](_r2); const item_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵreadContextLet"](0); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵnextContext"](); ctx_r0.hide(); return _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵresetView"](item_r3.open()); }); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"]()()(); } if (rf & 2) { const rawItem_r4 = ctx.$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵnextContext"](); const item_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵstoreLet"](ctx_r0.asItem(rawItem_r4)); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](item_r5.index); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](item_r5.date); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](item_r5.time); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate"](item_r5.annotator); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditional"](ctx_r0.hasPhaseLabels() ? 10 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵproperty"]("status", item_r5.reviewStatus); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵconditional"](item_r5.isLocal ? 14 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpipeBind1"](18, 9, "patientDetails.open"), " "); } } class InstancePickerComponent { popover; items = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)([], ...(ngDevMode ? [{ debugName: "items" }] : [])); hasPhaseLabels = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.items().some(item => item.phaseLabel), ...(ngDevMode ? [{ debugName: "hasPhaseLabels" }] : [])); onDocumentPointerDown(event) { const target = event.target; if (!target.closest('.instance-picker-popover') && !target.closest('lib-instance-picker')) { this.popover?.hide(); } } /** * Takes the element rather than the originating event: a menu command runs long after * its event was dispatched, by which point `currentTarget` is null. */ toggleAt(anchor) { this.popover?.toggle(new MouseEvent('click'), anchor); } hide() { this.popover?.hide(); document.querySelector('.instance-picker-popover')?.remove(); } asItem(value) { return value; } static ɵfac = function InstancePickerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InstancePickerComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵdefineComponent"]({ type: InstancePickerComponent, selectors: [["lib-instance-picker"]], viewQuery: function InstancePickerComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵviewQuery"](_c0, 5); } if (rf & 2) { let _t; _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵloadQuery"]()) && (ctx.popover = _t.first); } }, hostBindings: function InstancePickerComponent_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵlistener"]("pointerdown", function InstancePickerComponent_pointerdown_HostBindingHandler($event) { return ctx.onDocumentPointerDown($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵresolveDocument"]); } }, inputs: { items: [1, "items"] }, decls: 5, vars: 13, consts: [["popover", ""], ["data-test-id", "patient-library-p-popover-instance-picker", 3, "dt"], ["styleClass", "text-sm", 3, "value", "dt"], ["pTemplate", "header"], ["pTemplate", "body"], [1, "text-center"], [3, "status"], [1, "text-muted-color", "inline-flex", "cursor-default"], ["data-test-id", "patient-library-p-button-open-instance", "outlined", "", "size", "small", 3, "click"], ["icon", "check-circle"]], template: function InstancePickerComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementStart"](0, "p-popover", 1, 0)(2, "p-table", 2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵtemplate"](3, InstancePickerComponent_ng_template_3_Template, 20, 16, "ng-template", 3)(4, InstancePickerComponent_ng_template_4_Template, 19, 11, "ng-template", 4); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction1"](4, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction0"](3, _c1))); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵproperty"]("value", ctx.items())("dt", _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction3"](9, _c6, _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction0"](6, _c3), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction0"](7, _c4), _angular_core__WEBPACK_IMPORTED_MODULE_9__["ɵɵpureFunction0"](8, _c5))); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_3__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_3__.Button, primeng_api__WEBPACK_IMPORTED_MODULE_10__.PrimeTemplate, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__.IconComponent, primeng_popover__WEBPACK_IMPORTED_MODULE_4__.PopoverModule, primeng_popover__WEBPACK_IMPORTED_MODULE_4__.Popover, _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_7__.ReviewStatusIconComponent, primeng_table__WEBPACK_IMPORTED_MODULE_5__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_5__.Table, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 71086 /*!*************************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/patient-library-details.component.ts ***! \*************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PatientLibraryDetailsComponent: () => (/* binding */ PatientLibraryDetailsComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var primeng_progressspinner__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/progressspinner */ 7271); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _phase_selection_dialog_phase_selection_dialog_service__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../../../phase-selection-dialog/phase-selection-dialog.service */ 3124); /* harmony import */ var _services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../../services/dicom-annotation-codec */ 19462); /* harmony import */ var _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../review-status-icon/review-status-icon.component */ 92729); /* harmony import */ var _instance_picker_component__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./instance-picker.component */ 89442); /* harmony import */ var _patient_library_details_facade__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./patient-library-details.facade */ 21723); /* harmony import */ var _patient_library_list_facade__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./patient-library-list.facade */ 67045); /* harmony import */ var _series_bulk_actions_component__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./series-bulk-actions.component */ 36088); /* harmony import */ var _series_sort_store__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./series-sort.store */ 14900); const _c0 = a0 => ({ count: a0 }); const _c1 = () => ({ "min-width": "60rem", "table-layout": "fixed" }); const _c2 = a0 => ({ $implicit: a0 }); function PatientLibraryDetailsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", ctx_r1.error(), " "); } } function PatientLibraryDetailsComponent_For_6_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 33); } } function PatientLibraryDetailsComponent_For_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainer"](0, 32); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](1, PatientLibraryDetailsComponent_For_6_Conditional_1_Template, 1, 0, "div", 33); } if (rf & 2) { const template_r3 = ctx.$implicit; const ɵ$index_13_r4 = ctx.$index; const ɵ$count_13_r5 = ctx.$count; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const studySummaryTemplate_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](30); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ngTemplateOutlet", studySummaryTemplate_r6)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](3, _c2, template_r3)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](!(ɵ$index_13_r4 === ɵ$count_13_r5 - 1) ? 1 : -1); } } function PatientLibraryDetailsComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](0, "div", 13); } } function PatientLibraryDetailsComponent_ng_template_29_For_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "span", 39); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const title_r8 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](2, 1, title_r8)); } } function PatientLibraryDetailsComponent_ng_template_29_For_12_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "span", 39); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { const value_r9 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](value_r9); } } function PatientLibraryDetailsComponent_ng_template_29_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 34); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](1, "lib-icon", 35); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](2, "div")(3, "div")(4, "h3", 36); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](6, "div", 37)(7, "div", 38); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](8, PatientLibraryDetailsComponent_ng_template_29_For_9_Template, 3, 3, "span", 39, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIndex"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](10, "div", 40); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](11, PatientLibraryDetailsComponent_ng_template_29_For_12_Template, 2, 1, "span", 39, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIndex"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()()(); } if (rf & 2) { const data_r10 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("icon", data_r10.icon); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", data_r10.mainTitle, " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](data_r10.content.titles); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](data_r10.content.values); } } function PatientLibraryDetailsComponent_ng_template_33_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "tr")(1, "th", 41); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](2, "p-tableHeaderCheckbox"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](3, "th", 42)(4, "span", 43)(5, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](8, "p-sortIcon", 45); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](9, "th", 46)(10, "span", 43)(11, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](13, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](14, "p-sortIcon", 47); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](15, "th", 48)(16, "span", 43)(17, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](18); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](19, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](20, "p-sortIcon", 49); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](21, "th", 50)(22, "span", 43)(23, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](25, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](26, "p-sortIcon", 51); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](27, "th", 52)(28, "span", 53)(29, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](30); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](31, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](32, "p-sortIcon", 54); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](33, "th", 55)(34, "span", 53)(35, "span", 44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](36); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](37, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](38, "p-sortIcon", 56); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](39, "th", 57); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](40, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](41, "lib-icon", 58); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](42, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](43, "th", 59); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](44); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](45, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](7, 9, "patientDetails.table.modality")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](13, 11, "patientDetails.table.seriesNumber")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](19, 13, "patientDetails.table.description")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](25, 15, "patientDetails.table.seriesDate")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](31, 17, "patientDetails.table.images")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](37, 19, "patientDetails.table.approvalStatus")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](40, 21, "patientDetails.table.localCache")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](42, 23, "patientDetails.table.localCache")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](45, 25, "patientDetails.table.actions"), " "); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 73); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const total_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate2"](" ", total_r14 - series_r12.cache.cachedCount, "/", total_r14, " "); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 74); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](1, "p-progressBar", 75); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](2, "span", 76); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](4, "span", 77); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](5, "/"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](6, "span", 78); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const total_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("showValue", false)("value", total_r14 ? (total_r14 - series_r12.cache.cachedCount) / total_r14 * 100 : 0)("color", "var(--p-app-status-danger)"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](total_r14 - series_r12.cache.cachedCount); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](total_r14); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](1, PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Conditional_1_Template, 2, 2, "div", 73)(2, PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Conditional_2_Template, 8, 5, "div", 74); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const isOt_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](26); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"](ctx_r1.deletingSeriesTotalFiles()[series_r12.seriesInstanceUID] ?? series_r12.cache.totalCount); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](isOt_r15 ? 1 : 2); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_28_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 65)(1, "span", 79); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](3, "lib-icon", 80); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](2, 2, "patientDetails.cachedLocally")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](4, 4, "patientDetails.cachedLocally")); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_29_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 66); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](1, "p-progressBar", 81); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](2, "span", 76); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](4, "span", 77); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](5, "/"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](6, "span", 78); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("showValue", false)("value", series_r12.cache.percent); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", series_r12.cache.cachedCount, " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", series_r12.cache.totalCount, " "); } } function PatientLibraryDetailsComponent_ng_template_34_Conditional_30_Template(rf, ctx) { if (rf & 1) { const _r16 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 65)(1, "span", 82); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](3, "p-button", 83); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_ng_template_34_Conditional_30_Template_p_button_click_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.onDownloadSeries(series_r12)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](5, "lib-icon", 84); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r1.canAttempt(series_r12) ? _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](2, 3, "patientDetails.cacheLocally") : ctx_r1.getValidationTooltip(series_r12)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ariaLabel", ctx_r1.canAttempt(series_r12) ? _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](4, 5, "patientDetails.cacheLocally") : ctx_r1.getValidationTooltip(series_r12))("disabled", !ctx_r1.canAttempt(series_r12) || !series_r12.seriesInstanceUID || ctx_r1.downloadState()[series_r12.seriesInstanceUID] || ctx_r1.deleteState()[series_r12.seriesInstanceUID]); } } function PatientLibraryDetailsComponent_ng_template_34_Template(rf, ctx) { if (rf & 1) { const _r11 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](1, "tr", 60); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_ng_template_34_Template_tr_click_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.onRowClick(series_r12, $event)); })("dblclick", function PatientLibraryDetailsComponent_ng_template_34_Template_tr_dblclick_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.onRowDoubleClick(series_r12, $event)); })("contextmenu", function PatientLibraryDetailsComponent_ng_template_34_Template_tr_contextmenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const seriesMenuContext_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](41); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.seriesMenu.openAtPointer(seriesMenuContext_r13, $event, series_r12)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](2, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](3, "p-tableCheckbox", 61); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](4, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](6, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](7, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](9, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](10, "td", 62, 4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](13, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](14, "td", 62, 5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](16, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](18, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](19, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](20, "td", 63); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](22, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](23, "td", 63); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](24, "lib-review-status-icon", 64); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](25, "td", 63); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdeclareLet"](26); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](27, PatientLibraryDetailsComponent_ng_template_34_Conditional_27_Template, 3, 2)(28, PatientLibraryDetailsComponent_ng_template_34_Conditional_28_Template, 5, 6, "div", 65)(29, PatientLibraryDetailsComponent_ng_template_34_Conditional_29_Template, 8, 4, "div", 66)(30, PatientLibraryDetailsComponent_ng_template_34_Conditional_30_Template, 6, 7, "div", 65); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](31, "td")(32, "div", 67)(33, "span", 68)(34, "p-button", 69); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](35, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_ng_template_34_Template_p_button_click_34_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.openInVolumeViewer(series_r12, $event.currentTarget)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](36, "lib-icon", 70); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](37, "p-button", 71); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](38, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_ng_template_34_Template_p_button_click_37_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const series_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const seriesMenuPopup_r17 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](37); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r1.seriesMenu.openFromButton(seriesMenuPopup_r17, $event, series_r12)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](39, "lib-icon", 72); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const rawSeries_r18 = ctx.$implicit; const descriptionTip_r19 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](11); const seriesDateTip_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](15); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); const series_r21 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"](ctx_r1.asSeries(rawSeries_r18)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassProp"]("p-datatable-row-selected", ctx_r1.isSelected(series_r21)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pSelectableRow", series_r21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("data-series-uid", series_r21.seriesInstanceUID); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("value", series_r21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](6, 20, series_r21.modality)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](9, 22, series_r21.seriesNumber)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", descriptionTip_r19.truncated() ? series_r21.seriesDescription ?? undefined : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](13, 24, series_r21.seriesDescription), " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", seriesDateTip_r20.truncated() ? _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind3"](16, 26, series_r21.seriesDate, !!series_r21.seriesTime, series_r21.seriesTime) : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](19, 34, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind3"](18, 30, series_r21.seriesDate, !!series_r21.seriesTime, series_r21.seriesTime)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](22, 36, series_r21.totalInstanceCount)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("status", series_r21.reviewStatus); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵstoreLet"]((series_r21.modality == null ? null : series_r21.modality.toUpperCase()) === "OT"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r1.deleteState()[series_r21.seriesInstanceUID] ? 27 : series_r21.cache.percent === 100 ? 28 : series_r21.cache.totalCount > 0 && (series_r21.cache.cachedCount > 0 || ctx_r1.downloadState()[series_r21.seriesInstanceUID]) ? 29 : 30); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("pTooltip", ctx_r1.getValidationTooltip(series_r21))("tooltipDisabled", ctx_r1.canAttempt(series_r21)); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("disabled", !ctx_r1.canAttempt(series_r21) || !series_r21.seriesInstanceUID || !!ctx_r1.downloadState()[series_r21.seriesInstanceUID] || !!ctx_r1.deleteState()[series_r21.seriesInstanceUID] || ctx_r1.isOpening())("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](35, 39, "patientDetails.menu.view")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](38, 41, "patientDetails.table.actions")); } } function PatientLibraryDetailsComponent_ng_template_35_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 1, "patientDetails.loading"), " "); } } function PatientLibraryDetailsComponent_ng_template_35_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](1, 1, "patientDetails.noSeries"), " "); } } function PatientLibraryDetailsComponent_ng_template_35_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "tr")(1, "td", 85); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](2, PatientLibraryDetailsComponent_ng_template_35_Conditional_2_Template, 2, 3)(3, PatientLibraryDetailsComponent_ng_template_35_Conditional_3_Template, 2, 3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx_r1.loading() ? 2 : 3); } } const VIEWER_ROUTE = '/volume-viewer'; function readMetaTag(meta, tag) { return String(meta?.[tag]?.Value?.[0] ?? '').trim(); } /** Read a DICOM PN value, which may be a plain string or a `{ Alphabetic }` object. */ function readPersonName(value) { if (typeof value === 'string') return value.trim(); return ''; } class PatientLibraryDetailsComponent { router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_8__.Router); vm = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_patient_library_details_facade__WEBPACK_IMPORTED_MODULE_29__.PatientLibraryDetailsFacade); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_9__.TranslateService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_10__.MessageService); dialogRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_13__.DynamicDialogRef, { optional: true }); phaseSelectionDialog = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_phase_selection_dialog_phase_selection_dialog_service__WEBPACK_IMPORTED_MODULE_25__.PhaseSelectionDialogService); database = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.DicomDatabaseService); datePipe = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_1__.DatePipe); seriesSort = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_series_sort_store__WEBPACK_IMPORTED_MODULE_32__.SeriesSortStore); listFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_30__.PatientLibraryListFacade); destroyRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef); dicomPersonNamePipe = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.DicomPersonNamePipe); dicomDatePipe = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.DicomDatePipe); host = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_4__.ElementRef); studyUid = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "studyUid" }] : [])); storeUid = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "storeUid" }] : [])); cacheAllOnOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, ...(ngDevMode ? [{ debugName: "cacheAllOnOpen" }] : [])); // The study-level instance total from the study list's already-fetched row, when this store's // vendor provides one. Forwarded into the facade (see setContext below), which prefers it over // peekStudyInstanceCount - both the preference and the resulting instanceCount live there, in // summary(), so this component doesn't need to duplicate that logic. numberOfInstancesHint = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(undefined, ...(ngDevMode ? [{ debugName: "numberOfInstancesHint" }] : [])); viewMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)('list', ...(ngDevMode ? [{ debugName: "viewMode" }] : [])); back = new _angular_core__WEBPACK_IMPORTED_MODULE_3__.EventEmitter(); loading = this.vm.loading; error = this.vm.error; seriesList = this.vm.seriesList; hasAnnotatedSeries = this.vm.hasAnnotatedSeries; deleteState = this.vm.deleteState; downloadState = this.vm.downloadState; loadSeries = (force = false) => this.vm.loadSeries(force); deleteSeries = seriesUid => this.vm.deleteSeries(seriesUid); summary = this.vm.summary; sortField = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.seriesSort.sortSpec()?.field, ...(ngDevMode ? [{ debugName: "sortField" }] : [])); sortOrder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.seriesSort.sortSpec()?.direction ?? _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.PRIMENG_DEFAULT_SORT_ORDER, ...(ngDevMode ? [{ debugName: "sortOrder" }] : [])); instancePicker; statusFilter = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(undefined, ...(ngDevMode ? [{ debugName: "statusFilter" }] : [])); langChange = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_6__.toSignal)(this.translate.onLangChange); statusFilterOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { this.langChange(); return ['approved', 'rejected', 'unapproved'].map(value => ({ label: this.translate.instant(`reviewStatus.${value}`), value })); }, ...(ngDevMode ? [{ debugName: "statusFilterOptions" }] : [])); displayedSeries = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const status = this.statusFilter(); const list = this.seriesList(); // Copy so PrimeNG's in-place column sort doesn't mutate the facade's signal array. return status ? list.filter(series => series.reviewStatus === status) : [...list]; }, ...(ngDevMode ? [{ debugName: "displayedSeries" }] : [])); studySummary = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(undefined, ...(ngDevMode ? [{ debugName: "studySummary" }] : [])); seriesMenu = new _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.RowMenuController((series, anchor) => this.buildSeriesMenuItems(series, anchor)); activeInstanceItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "activeInstanceItems" }] : [])); deletingSeriesTotalFiles = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)({}, ...(ngDevMode ? [{ debugName: "deletingSeriesTotalFiles" }] : [])); // Phase/instance-picker resolution before navigation can take a noticeable moment - this // blocks re-entry into openInVolumeViewer for that whole span so a slow click doesn't get // mistaken for a missed one and re-triggered. isOpening = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isOpening" }] : [])); selectedSeries = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "selectedSeries" }] : [])); anchorSeriesUid; cacheAllRequestedUids = new Set(); _studySummaryRequestId = 0; // p-table's own internal row-rendering *ngFor runs over [value] directly, using [rowTrackBy] - // which defaults to raw object identity. seriesList() hands it a brand-new object for the row // being cached on every progress tick, so without this, Angular's default trackBy sees "a // different row" on every tick and destroys+recreates that row's entire embedded view, // checkbox included - a fresh p-tableCheckbox starts unchecked until its own ngOnInit reruns, // which is the actual checked-state flip (TVC bug: "Entry-selecting checkbox flickers while // application pre-caches image data"), not just a repaint. trackBySeriesUid = (_index, item) => item.seriesInstanceUID ?? item; // Narrows seriesList()[0] down to just the fields the summary effect below actually cares // about, with an equality check over them - seriesList() gets a new array (and new item // objects) every time any series' peeked totalInstanceCount arrives, which happens once per // series as the table's counts fill in. Without this, the summary effect below re-read that // unrelated churn as "the first series changed", re-running its network peek and clobbering // the already-resolved patientBirthDate/studyTime with the synchronous fallback on every // single instance-count update - the heading flashing back to '-' and re-filling repeatedly. firstSeriesSummarySource = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const first = this.seriesList()[0]; if (!first?.seriesInstanceUID) return; return { patientID: first.patientID, patientName: first.patientName, seriesInstanceUID: first.seriesInstanceUID, studyDate: first.studyDate, studyDescription: first.studyDescription }; }, { ...(ngDevMode ? { debugName: "firstSeriesSummarySource" } : {}), equal: (a, b) => a?.seriesInstanceUID === b?.seriesInstanceUID && a?.patientID === b?.patientID && a?.patientName === b?.patientName && a?.studyDate === b?.studyDate && a?.studyDescription === b?.studyDescription }); constructor() { this.listFacade.detailsToolbar.set({ loading: this.loading, reload: () => this.loadSeries(true) }); this.destroyRef.onDestroy(() => this.listFacade.detailsToolbar.set(undefined)); // Native OS busy cursor for the open-scan span: opening can take a moment before the // volume viewer's own progress bar takes over, and the button being disabled isn't visible // if the mouse isn't over it. Toggled on (not scoped to this component's DOM) with // `!important` on every descendant so it overrides elements that set their own cursor // (buttons, links). Cleared on destroy - this component is torn down when navigation to the // viewer completes, which is exactly the point its own loading state should take over. (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { document.body.classList.toggle('app-cursor-wait', this.isOpening()); }); this.destroyRef.onDestroy(() => document.body.classList.remove('app-cursor-wait')); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.vm.setContext(this.studyUid(), this.storeUid(), this.numberOfInstancesHint()); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { const first = this.firstSeriesSummarySource(); const requestId = ++this._studySummaryRequestId; if (!first?.seriesInstanceUID) { // No series (yet, or this study genuinely has none) - clear rather than leave a // previous study's summary on screen. this.studySummary.set(undefined); return; } const studyUid = this.studyUid(); const storeUid = this.storeUid(); // Immediate fallback from fields the series-list item already carries, so the heading // doesn't show '-' for data that was never actually behind the peek below. this.studySummary.set({ patientBirthDate: undefined, patientID: first.patientID ?? undefined, patientName: first.patientName ?? undefined, studyDate: first.studyDate ?? undefined, studyDescription: first.studyDescription ?? undefined, studyTime: undefined }); // Fills in the richer fields (patientBirthDate, studyTime) the series-list item doesn't // carry. peekSeriesCommonMetadata prefers whatever's already cached locally, and only // reaches the network on a cold cache - without ever persisting the response, so peeking // at this info for the heading can't grow local storage or resurrect an evicted series' // metadata rows. this.database.peekSeriesCommonMetadata(studyUid, first.seriesInstanceUID, storeUid).then(meta => { if (requestId !== this._studySummaryRequestId) return; this.studySummary.set({ patientBirthDate: meta?.patientBirthDate, patientID: meta?.patientID ?? first.patientID ?? undefined, patientName: meta?.patientName ?? first.patientName ?? undefined, studyDate: meta?.studyDate ?? first.studyDate ?? undefined, studyDescription: meta?.studyDescription ?? first.studyDescription ?? undefined, studyTime: this.formatDicomTime(meta?.studyTime) }); }).catch(() => { // Non-fatal: leave the synchronous fallback set above in place rather than clearing // it - the richer fields just stay unavailable for this series. }); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { const list = this.seriesList(); const selectedUids = new Set((0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(this.selectedSeries).map(s => s.seriesInstanceUID)); if (selectedUids.size === 0) return; this.selectedSeries.set(list.filter(s => s.seriesInstanceUID && selectedUids.has(s.seriesInstanceUID))); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { if (!this.cacheAllOnOpen()) return; const list = this.seriesList(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => this.cacheSeriesOnce(list)); }); } // Renders both cards immediately with per-field '-' placeholders rather than waiting for // studySummary to fully resolve and flashing the whole heading in at once - each field fills // in on its own once the underlying peek (or richer local metadata) provides it. headingTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const s = this.studySummary(); const dateOfBirth = this.dicomDatePipe.transform(s?.patientBirthDate) ?? '-'; const patientId = s?.patientID ?? '-'; const studyDate = this.dicomDatePipe.transform(s?.studyDate) ?? '-'; const studyTime = s?.studyTime ?? '-'; return [{ content: { titles: ['patientDetails.heading.dateOfBirth', 'patientDetails.heading.patientId'], values: [dateOfBirth, patientId] }, icon: 'user', mainTitle: this.dicomPersonNamePipe.transform(s?.patientName) ?? '-' }, { content: { titles: ['patientDetails.heading.studyDate', 'patientDetails.heading.studyTime'], values: [studyDate, studyTime] }, icon: 'folder', mainTitle: s?.studyDescription ?? '-' }]; }, ...(ngDevMode ? [{ debugName: "headingTemplate" }] : [])); formatDicomDate(raw) { const d = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.parseDicomDate)(raw); return d ? this.datePipe.transform(d, 'MMM d, y') ?? raw : raw; } formatDicomTime(raw) { if (!raw || raw.length < 6) return raw; return `${raw.slice(0, 2)}:${raw.slice(2, 4)}:${raw.slice(4, 6)}`; } openInVolumeViewer(series, anchor) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this.isOpening()) return; const seriesUid = series.seriesInstanceUID; if (!seriesUid || !_this.canAttempt(series) || _this.downloadState()[seriesUid] || _this.deleteState()[seriesUid]) { return; } const isOt = _this.isOtModality(series); _this.isOpening.set(true); try { if (isOt) { yield _this.openOtSeriesInViewer(series, seriesUid, anchor); return; } const selectedPhaseIds = yield _this.phaseSelectionDialog.selectForSeries(_this.studyUid(), seriesUid, _this.storeUid()); if (selectedPhaseIds === undefined) return; _this.vm.downloadSeries(seriesUid); _this.dialogRef?.close(); yield _this.router.navigate([VIEWER_ROUTE, _this.storeUid(), _this.studyUid(), seriesUid, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.WORK_SESSION_NEW_KEY], { queryParams: { ...(selectedPhaseIds.length > 0 ? { phases: selectedPhaseIds.join(',') } : {}) } }); } finally { _this.isOpening.set(false); } })(); } openOtSeriesInViewer(series, seriesUid, anchor) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (anchor && (yield _this2.tryShowInstancePicker(series, seriesUid, anchor))) return; const { otSeriesUid, targetSeriesUid } = yield _this2.resolveViewerTarget(series, seriesUid); if (otSeriesUid) { _this2.vm.downloadSeries(targetSeriesUid); } _this2.dialogRef?.close(); yield _this2.router.navigate([VIEWER_ROUTE, _this2.storeUid(), _this2.studyUid(), targetSeriesUid, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.WORK_SESSION_NEW_KEY], { queryParams: { ...(otSeriesUid ? { otSeriesUid } : {}) } }); })(); } tryShowInstancePicker(series, seriesUid, anchor) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const studyUid = _this3.studyUid(); if (!studyUid) return false; const instances = yield _this3.database.getSeriesInstancesMetadata(studyUid, seriesUid, _this3.storeUid()); if (instances.length <= 1) return false; _this3.activeInstanceItems.set(instances.map((inst, index) => _this3.buildInstanceItem(series, inst, index, !!inst.getAttachment('pixelData')))); _this3.instancePicker?.toggleAt(anchor); return true; })(); } openOtInstance(series, inst) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this4.isOpening()) return; _this4.isOpening.set(true); try { const seriesUid = series.seriesInstanceUID ?? ''; // Same definitive check as resolveWorkSessionInstance - a "referenced series" tag alone // isn't proof this specific instance is a genuine Tomoverse work session. const meta = inst.toJSON().metadata; if (!meta) return; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_21__.isTvctWorkSessionInstance)(meta)) { _this4.vm.error.set(_this4.translate.instant('patientDetails.instancePicker.notWorkSession')); return; } const sourceSeriesUid = yield _this4.resolveSourceFromInstance(inst); if (!sourceSeriesUid) return; _this4.vm.downloadSeries(sourceSeriesUid); _this4.dialogRef?.close(); yield _this4.router.navigate([VIEWER_ROUTE, _this4.storeUid(), _this4.studyUid(), sourceSeriesUid, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.WORK_SESSION_NEW_KEY], { queryParams: { otInstanceUid: inst.sopInstanceUID, otSeriesUid: seriesUid } }); } finally { _this4.isOpening.set(false); } })(); } resolveViewerTarget(series, seriesUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const notOt = { otSeriesUid: undefined, targetSeriesUid: seriesUid, workSessionName: undefined, workSessionUid: undefined }; if (!_this5.isOtModality(series)) return notOt; const studyUid = _this5.studyUid(); if (!studyUid) return notOt; const workSession = yield _this5.resolveWorkSessionInstance(studyUid, seriesUid); if (!workSession) return notOt; const sourceSeriesUid = yield _this5.resolveSourceFromInstance(workSession.firstInstance); if (!sourceSeriesUid) return notOt; const workSessionUid = readMetaTag(workSession.meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.TvctWorkSessionUid) || undefined; const workSessionName = readMetaTag(workSession.meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.SeriesDescription) || undefined; return { otSeriesUid: seriesUid, targetSeriesUid: sourceSeriesUid, workSessionName, workSessionUid }; })(); } /** * Fetches (and caches) the series' instances, returning its first instance and metadata only * if a definitive, instance-level check confirms this is a genuine Tomoverse work session - a * "referenced series" tag alone isn't proof, since any secondary-capture OT file could have one. */ resolveWorkSessionInstance(studyUid, seriesUid) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const instances = yield _this6.database.getSeriesInstancesMetadata(studyUid, seriesUid, _this6.storeUid()); const [firstInstance] = instances; if (!firstInstance) return undefined; const meta = firstInstance.toJSON().metadata; if (!meta || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_21__.isTvctWorkSessionInstance)(meta)) return undefined; return { firstInstance, meta }; })(); } resolveSourceFromInstance(inst) { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const meta = inst.toJSON().metadata; let sourceSeriesUid = String(meta?.[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.ReferencedSeriesSequence]?.Value?.[0]?.[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.SeriesInstanceUID]?.Value?.[0] ?? '').trim(); if (!sourceSeriesUid) { try { const binary = yield _this7.database.getBinary(inst.sopInstanceUID, _this7.storeUid()); sourceSeriesUid = (0,_services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_26__.extractAnnotationTags)(binary)?.sourceSeriesUid ?? ''; } catch { // binary unavailable — fall through } } if (!sourceSeriesUid) return ''; const studyUid = _this7.studyUid(); if (!studyUid || !(yield _this7.seriesExistsInStore(studyUid, sourceSeriesUid))) { _this7.messageService.add({ life: 4000, severity: 'warn', summary: _this7.translate.instant('patientDetails.sourceSeriesMissing') }); return ''; } return sourceSeriesUid; })(); } // An OT file's embedded/tagged source series reference can point at a series the store no // longer has (e.g. the original CT was never uploaded to this store, or was deleted) - without // this check, navigating ahead anyway only surfaces a raw 404 once the viewer tries to load it. seriesExistsInStore(studyUid, seriesUid) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const instances = yield _this8.database.getSeriesInstancesMetadata(studyUid, seriesUid, _this8.storeUid()); return instances.length > 0; } catch { return false; } })(); } buildInstanceItem(series, inst, index, isLocal) { const meta = inst.toJSON().metadata; const rawDate = readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.InstanceCreationDate); const rawTime = readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.InstanceCreationTime); const annotator = readPersonName(meta?.[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.TvctAuthorName]?.Value?.[0]); const phaseLabel = readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.TvctPhaseLabel) || undefined; // Private mirror fallback in case the store dropped the non-indexed standard tag. const approvalStatus = readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.ApprovalStatus) || readMetaTag(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_22__.DicomTagId.TvctReviewStatus); return { annotator: annotator || '—', date: (this.formatDicomDate(rawDate) ?? rawDate) || '—', index: index + 1, isLocal, open: () => { this.openOtInstance(series, inst); }, phaseLabel, reviewStatus: (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.approvalToReviewStatus)(approvalStatus), time: rawTime ? this.formatDicomTime(rawTime) ?? rawTime : '—' }; } onRowDoubleClick(series, event) { this.openInVolumeViewer(series, event.currentTarget); } // A plain click must leave selection alone, which rules out pSelectableRow: its plain-click // branch always selects, even under metaKeySelection. onRowClick(series, event) { // The checkbox and action buttons answer their own clicks; without this a ctrl-click on the // checkbox toggles twice. if (event.target.closest('p-tablecheckbox, .p-checkbox, button, a')) return; const seriesUid = series.seriesInstanceUID; if (event.shiftKey && this.anchorSeriesUid) { this.selectRangeTo(seriesUid); return; } if (!event.ctrlKey && !event.metaKey) return; this.anchorSeriesUid = seriesUid; this.selectedSeries.update(selected => selected.some(s => s.seriesInstanceUID === seriesUid) ? selected.filter(s => s.seriesInstanceUID !== seriesUid) : [...selected, series]); } // Row order comes from the DOM because sorting reorders the screen, not seriesList(). selectRangeTo(seriesUid) { const anchor = this.anchorSeriesUid; if (!seriesUid || !anchor) return; const order = [...this.host.nativeElement.querySelectorAll('[data-series-uid]')].map(row => row.dataset['seriesUid']).filter(uid => !!uid); const from = order.indexOf(anchor); const to = order.indexOf(seriesUid); if (from === -1 || to === -1) return; const inRange = new Set(order.slice(Math.min(from, to), Math.max(from, to) + 1)); this.selectedSeries.set(this.seriesList().filter(s => s.seriesInstanceUID && inRange.has(s.seriesInstanceUID))); } clearSelection() { this.selectedSeries.set([]); // Without this a later shift-click would extend from the cleared selection's anchor. this.anchorSeriesUid = undefined; } isSelected(series) { return this.selectedSeries().some(s => s.seriesInstanceUID === series.seriesInstanceUID); } onSort(event) { const field = event.field; this.seriesSort.setSort(field ? { direction: event.order ?? 1, field } : undefined); } canOpen(series) { const seriesUid = series.seriesInstanceUID; return Boolean(seriesUid && this.isSupported(series) && !this.downloadState()[seriesUid] && !this.deleteState()[seriesUid]); } canCache(series) { return this.canOpen(series) && !(0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.isSeriesFullyCached)(series.cache); } canDelete(series) { const seriesUid = series.seriesInstanceUID; return Boolean(seriesUid && (series.cache.totalCount > 0 || series.cache.cachedCount > 0) && !this.downloadState()[seriesUid] && !this.deleteState()[seriesUid]); } cacheableSelected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.selectedSeries().filter(s => s.seriesInstanceUID && !(0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.isSeriesFullyCached)(s.cache) && this.canAttempt(s) && !this.downloadState()[s.seriesInstanceUID] && !this.deleteState()[s.seriesInstanceUID]), ...(ngDevMode ? [{ debugName: "cacheableSelected" }] : [])); deletableSelected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => this.selectedSeries().filter(s => this.canDelete(s)), ...(ngDevMode ? [{ debugName: "deletableSelected" }] : [])); viewBlockedReason = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const selected = this.selectedSeries(); if (selected.length > 1) { return this.translate.instant('patientDetails.bulkActions.viewOneOnly'); } const [series] = selected; if (!series || this.canOpen(series) || this.isOtModality(series)) return ''; return this.getValidationTooltip(series); }, ...(ngDevMode ? [{ debugName: "viewBlockedReason" }] : [])); onBulkView() { if (this.viewBlockedReason()) return; const [series] = this.selectedSeries(); if (series) this.openInVolumeViewer(series); } onBulkDownload() { const uids = this.cacheableSelected().map(s => s.seriesInstanceUID).filter(uid => !!uid); if (uids.length === 0) return; this.vm.downloadSeriesBatch(uids, uids.length === 1 ? undefined : this.translate.instant('patientDetails.caching.selectedSeries', { count: uids.length })); this.clearSelection(); } cacheSeriesOnce(list) { const uids = []; for (const s of list) { const seriesUid = s.seriesInstanceUID; if (!seriesUid || this.cacheAllRequestedUids.has(seriesUid) || !this.canCache(s)) continue; this.cacheAllRequestedUids.add(seriesUid); uids.push(seriesUid); } if (uids.length === 0) return; this.vm.downloadSeriesBatch(uids, uids.length === 1 ? undefined : this.translate.instant('patientDetails.caching.selectedSeries', { count: uids.length })); } bulkMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.computed)(() => { const blocked = this.viewBlockedReason(); return [{ command: () => this.onBulkView(), disabled: !!blocked, icon: 'pi pi-eye', label: blocked || this.translate.instant('patientDetails.bulkActions.view') }, { separator: true }, { command: () => this.onBulkDownload(), disabled: this.cacheableSelected().length === 0, icon: 'pi pi-cloud-download', label: this.translate.instant('patientDetails.menu.cache') }, { separator: true }, { command: () => this.selectedSeries.set([...this.seriesList()]), disabled: this.selectedSeries().length === this.seriesList().length, icon: 'pi pi-check-square', label: this.translate.instant('patientDetails.menu.selectAll') }, { command: () => this.clearSelection(), disabled: this.selectedSeries().length === 0, icon: 'pi pi-stop', label: this.translate.instant('patientDetails.menu.deselectAll') }, { separator: true }, (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.dangerMenuItem)({ command: () => this.onBulkDeleteLocalStorage(), disabled: this.deletableSelected().length === 0, icon: 'pi pi-ban', label: this.translate.instant('patientDetails.menu.delete') })]; }, ...(ngDevMode ? [{ debugName: "bulkMenuItems" }] : [])); onBulkDeleteLocalStorage() { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // Sequential, not fired concurrently: deleteSeriesCache races against itself across series // when run in parallel (each removes its own instance documents from the same RxDB // collection), which was silently dropping every deletion after the first. for (const s of _this9.deletableSelected()) { yield _this9.deleteSeriesWithProgress(s); } })(); } /** deleteSeriesCache removes each instance document outright rather than just clearing its * attachment, so the live `series.cache.totalCount` this row is bound to shrinks along with * `cachedCount` as the delete progresses - showing a stuck "0/N" ticking down to "0/0" * instead of "N/N" ticking down to "0/N". Snapshotting the starting total here (read via * `deletingSeriesTotalFiles` in the template) keeps the denominator fixed for the duration. */ deleteSeriesWithProgress(series) { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const seriesUid = series.seriesInstanceUID; if (!seriesUid) return; _this0.deletingSeriesTotalFiles.update(state => ({ ...state, [seriesUid]: series.cache.totalCount })); try { yield _this0.deleteSeries(seriesUid); } finally { _this0.deletingSeriesTotalFiles.update(state => { const next = { ...state }; delete next[seriesUid]; return next; }); } })(); } onBack() { this.back.emit(); } onDownloadSeries(series) { const seriesUid = series.seriesInstanceUID; if (!seriesUid || !this.canAttempt(series)) { return; } this.vm.downloadSeries(seriesUid); } buildSeriesMenuItems(series, anchor) { return [{ command: () => this.openInVolumeViewer(series, anchor), disabled: !this.canOpen(series), icon: 'pi pi-box', label: this.translate.instant('patientDetails.menu.view') }, { separator: true }, { command: () => this.onDownloadSeries(series), disabled: !this.canCache(series), icon: 'pi pi-cloud-download', label: this.translate.instant('patientDetails.menu.cache') }, { separator: true }, { command: () => this.selectedSeries.set([...this.seriesList()]), disabled: this.selectedSeries().length === this.seriesList().length, icon: 'pi pi-check-square', label: this.translate.instant('patientDetails.menu.selectAll') }, { command: () => this.clearSelection(), disabled: this.selectedSeries().length === 0, icon: 'pi pi-stop', label: this.translate.instant('patientDetails.menu.deselectAll') }, { separator: true }, (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.dangerMenuItem)({ command: () => this.deleteSeriesWithProgress(series), disabled: !this.canDelete(series), icon: 'pi pi-ban', label: this.translate.instant('patientDetails.menu.delete') }), (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.dangerMenuItem)({ disabled: true, icon: 'pi pi-trash', label: this.translate.instant('patientDetails.menu.deleteFromStore') })]; } asSeries(value) { return value; } isSupported(series) { return this.getValidationErrors(series).length === 0; } /** * Whether an action (open/download) should be attempted at all. isSupported() reflects * validationErrors computed from whatever's already cached locally, which is empty - and * therefore wrongly flags a modality mismatch - for any OT series never fetched before. OT * series defer their real validity check to the on-demand fetch (resolveWorkSessionInstance), * so they're always attemptable here regardless of that possibly-stale snapshot. */ canAttempt(series) { return this.isSupported(series) || this.isOtModality(series); } isOtModality(series) { return String(series.modality ?? '').trim().toUpperCase() === 'OT'; } getValidationTooltip(series) { return this.getValidationErrors(series).join('\n'); } setViewMode(mode) { this.viewMode.set(mode); } getValidationErrors(series) { return series.validationErrors ?? []; } static ɵfac = function PatientLibraryDetailsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PatientLibraryDetailsComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineComponent"]({ type: PatientLibraryDetailsComponent, selectors: [["lib-patient-library-details"]], viewQuery: function PatientLibraryDetailsComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵviewQuery"](_instance_picker_component__WEBPACK_IMPORTED_MODULE_28__.InstancePickerComponent, 5); } if (rf & 2) { let _t; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵloadQuery"]()) && (ctx.instancePicker = _t.first); } }, hostAttrs: [1, "block", "h-full"], inputs: { studyUid: [1, "studyUid"], storeUid: [1, "storeUid"], cacheAllOnOpen: [1, "cacheAllOnOpen"], numberOfInstancesHint: [1, "numberOfInstancesHint"] }, outputs: { back: "back" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵProvidersFeature"]([_angular_common__WEBPACK_IMPORTED_MODULE_1__.DatePipe, _patient_library_details_facade__WEBPACK_IMPORTED_MODULE_29__.PatientLibraryDetailsFacade, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.DicomPersonNamePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.DicomDatePipe])], decls: 43, vars: 40, consts: [["studySummaryTemplate", ""], ["seriesMenuPopup", ""], ["bulkMenu", ""], ["seriesMenuContext", ""], ["descriptionTip", "libEllipsisTip"], ["seriesDateTip", "libEllipsisTip"], [1, "flex", "h-full", "min-h-0", "flex-col"], [1, "border-destructive/30", "bg-destructive/10", "text-destructive", "mx-4", "mb-4", "shrink-0", "rounded-md", "border", "px-3", "py-2"], [1, "mx-4", 3, "back", "backAriaLabel"], ["left", ""], ["right", ""], [1, "flex", "items-center", "gap-4"], [3, "view", "cache", "clear", "more", "selectedCount", "cacheableCount", "viewBlockedReason"], [1, "h-8", "w-px", "bg-(--p-app-surface-tab)"], ["data-test-id", "patient-library-p-select-status-filter", "optionLabel", "label", "optionValue", "value", "size", "small", "appendTo", "body", 1, "overflow-hidden", 3, "ngModelChange", "options", "ngModel", "showClear", "placeholder"], ["data-test-id", "patient-library-div-series-summary", 1, "text-muted-color", "mb-2", "flex", "shrink-0", "items-center", "gap-2", "pt-2", "text-sm"], [1, "hidden", "h-8", "w-px", "bg-(--p-app-surface-tab)"], [1, "hidden"], [1, "flex", "gap-1", "rounded-md", "bg-(--p-app-neutral-950)", "p-1"], ["data-test-id", "patient-library-p-button-view-list", "severity", "secondary", "size", "large", "variant", "text", 3, "click", "severity"], ["icon", "list"], ["data-test-id", "patient-library-p-button-view-grid", "severity", "secondary", "size", "large", "variant", "text", 3, "click", "severity"], ["icon", "th-large"], [1, "min-h-0", "flex-1"], ["dataKey", "seriesInstanceUID", "scrollable", "", "scrollHeight", "flex", "selectionMode", "multiple", 1, "library-table", 3, "selectionChange", "onSort", "value", "loading", "rowTrackBy", "tableStyle", "selection", "sortField", "sortOrder"], ["pTemplate", "header"], ["pTemplate", "body"], ["pTemplate", "emptymessage"], ["data-test-id", "patient-library-p-menu-series", "popup", "", "appendTo", "body", 3, "model"], ["data-test-id", "patient-library-p-menu-bulk", "popup", "", "appendTo", "body", 3, "model"], ["data-test-id", "patient-library-p-contextmenu-series", "appendTo", "body", 3, "model"], [3, "items"], [3, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "mr-2", "ml-2", "h-12", "w-px", "bg-(--p-app-surface-tab)"], [1, "flex", "items-center", "gap-3"], [1, "flex", "size-10", "items-center", "justify-center", "rounded-full", "bg-(--p-app-neutral-800)", "[&_svg]:size-5", 3, "icon"], [1, "text-color", "pb-1", "text-base", "font-semibold"], [1, "flex", "gap-3"], [1, "text-muted-color", "flex", "flex-col", "text-xs"], [1, "pb-0.5"], [1, "flex", "flex-col", "text-xs", "text-(--p-app-neutral-300)"], [1, "w-[4.125rem]"], ["pSortableColumn", "modality", 1, "w-[6.875rem]", "overflow-hidden"], [1, "flex", "min-w-0", "items-center", "gap-1"], [1, "truncate"], ["field", "modality"], ["pSortableColumn", "seriesNumber", 1, "w-[9.6875rem]", "overflow-hidden"], ["field", "seriesNumber"], ["pSortableColumn", "seriesDescription", 1, "overflow-hidden"], ["field", "seriesDescription"], ["pSortableColumn", "seriesDate", 1, "w-[11.5625rem]", "overflow-hidden"], ["field", "seriesDate"], ["pSortableColumn", "totalInstanceCount", 1, "w-[6.25rem]", "overflow-hidden", "text-center"], [1, "flex", "min-w-0", "items-center", "justify-center", "gap-1"], ["field", "totalInstanceCount"], ["pSortableColumn", "reviewStatusRank", 1, "w-[8.4375rem]", "overflow-hidden", "text-center"], ["field", "reviewStatusRank"], ["tooltipPosition", "top", 1, "w-[3.125rem]", "text-center", "whitespace-nowrap", 3, "pTooltip"], ["icon", "cloud-download", 1, "text-muted-color"], [1, "w-[8.4375rem]", "text-center", "whitespace-nowrap"], [3, "click", "dblclick", "contextmenu", "pSelectableRow"], [3, "value"], ["libEllipsisTip", "", "tooltipPosition", "top", 3, "pTooltip"], [1, "text-center"], [3, "status"], [1, "flex", "items-center", "justify-center", "gap-2"], [1, "text-muted-color", "flex", "items-center", "text-xs"], [1, "flex", "items-center", "justify-end", "gap-2"], ["tooltipPosition", "top", 1, "inline-flex", 3, "pTooltip", "tooltipDisabled"], ["data-test-id", "patient-library-p-button-open-series", "rounded", "", "text", "", "size", "small", "styleClass", "h-[30px] w-[30px] p-0", 3, "click", "disabled", "ariaLabel"], ["icon", "eye", 1, "size-(--p-app-icon-size-xs)"], ["data-test-id", "patient-library-p-button-series-menu", "severity", "secondary", "text", "", "size", "small", 3, "click", "ariaLabel"], ["icon", "ellipsis-v"], [1, "flex", "justify-center", "text-xs", "text-(--p-app-status-danger)"], [1, "flex", "items-center", "text-xs", "text-(--p-app-status-danger)"], [1, "mr-2", "h-2", "w-24", 3, "showValue", "value", "color"], [1, "w-10", "text-right"], [1, "w-2"], [1, "w-5"], ["tooltipPosition", "top", 1, "text-muted-color", "inline-flex", "cursor-default", 3, "pTooltip"], ["icon", "check-circle"], [1, "mr-2", "h-2", "w-24", 3, "showValue", "value"], ["tooltipPosition", "top", 1, "inline-flex", 3, "pTooltip"], ["data-test-id", "patient-library-p-button-download-series", "severity", "secondary", "rounded", "", "text", "", "size", "small", "styleClass", "h-[30px] w-[30px] p-0", 3, "click", "ariaLabel", "disabled"], ["icon", "cloud-download", 1, "size-(--p-app-icon-size-xs)"], ["colspan", "9", 1, "text-center"]], template: function PatientLibraryDetailsComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](1, PatientLibraryDetailsComponent_Conditional_1_Template, 2, 1, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](2, "lib-heading-area", 8); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("back", function PatientLibraryDetailsComponent_Template_lib_heading_area_back_2_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.onBack()); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainerStart"](4, 9); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterCreate"](5, PatientLibraryDetailsComponent_For_6_Template, 2, 5, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeaterTrackByIndex"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainerEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainerStart"](7, 10); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](8, "div", 11)(9, "lib-series-bulk-actions", 12); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("view", function PatientLibraryDetailsComponent_Template_lib_series_bulk_actions_view_9_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.onBulkView()); })("cache", function PatientLibraryDetailsComponent_Template_lib_series_bulk_actions_cache_9_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.onBulkDownload()); })("clear", function PatientLibraryDetailsComponent_Template_lib_series_bulk_actions_clear_9_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.clearSelection()); })("more", function PatientLibraryDetailsComponent_Template_lib_series_bulk_actions_more_9_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); const bulkMenu_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵreference"](39); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](bulkMenu_r7.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](10, PatientLibraryDetailsComponent_Conditional_10_Template, 1, 0, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](11, "p-select", 14); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("ngModelChange", function PatientLibraryDetailsComponent_Template_p_select_ngModelChange_11_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.statusFilter.set($event ?? undefined)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](13, "div", 15)(14, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](15); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](16, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](17, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](18, "\u00B7"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](19, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtext"](20); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipe"](21, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](22, "div", 16); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](23, "div", 17)(24, "div", 18)(25, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_Template_p_button_click_25_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.setViewMode("list")); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](26, "lib-icon", 20); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](27, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("click", function PatientLibraryDetailsComponent_Template_p_button_click_27_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.setViewMode("grid")); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](28, "lib-icon", 22); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementContainerEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](29, PatientLibraryDetailsComponent_ng_template_29_Template, 13, 2, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](31, "div", 23)(32, "p-table", 24); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("selectionChange", function PatientLibraryDetailsComponent_Template_p_table_selectionChange_32_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.selectedSeries.set($event ?? [])); })("onSort", function PatientLibraryDetailsComponent_Template_p_table_onSort_32_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.onSort($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtemplate"](33, PatientLibraryDetailsComponent_ng_template_33_Template, 46, 27, "ng-template", 25)(34, PatientLibraryDetailsComponent_ng_template_34_Template, 40, 43, "ng-template", 26)(35, PatientLibraryDetailsComponent_ng_template_35_Template, 4, 1, "ng-template", 27); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelement"](36, "p-menu", 28, 1)(38, "p-menu", 29, 2)(40, "p-contextmenu", 30, 3)(42, "lib-instance-picker", 31); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx.error() ? 1 : -1); const headingTemplateData_r22 = ctx.headingTemplate(); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("backAriaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](3, 25, "patientDetails.back")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrepeater"](headingTemplateData_r22); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("selectedCount", ctx.selectedSeries().length)("cacheableCount", ctx.cacheableSelected().length)("viewBlockedReason", ctx.viewBlockedReason()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx.selectedSeries().length > 0 ? 10 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("options", ctx.statusFilterOptions())("ngModel", ctx.statusFilter())("showClear", true)("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind1"](12, 27, "reviewStatus.all")); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind2"](16, 29, "patientDetails.counts.series", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](35, _c0, ctx.summary().seriesCount)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpipeBind2"](21, 32, "patientDetails.counts.instances", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction1"](37, _c0, ctx.summary().instanceCount ?? "-")), " "); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("severity", ctx.viewMode() === "list" ? "primary" : "secondary"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("severity", ctx.viewMode() === "grid" ? "primary" : "secondary"); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("value", ctx.displayedSeries())("loading", ctx.loading())("rowTrackBy", ctx.trackBySeriesUid)("tableStyle", _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵpureFunction0"](39, _c1))("selection", ctx.selectedSeries())("sortField", ctx.sortField())("sortOrder", ctx.sortOrder()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("model", ctx.seriesMenu.items()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("model", ctx.bulkMenuItems()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("model", ctx.seriesMenu.items()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("items", ctx.activeInstanceItems()); } }, dependencies: [primeng_table__WEBPACK_IMPORTED_MODULE_18__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_18__.Table, primeng_api__WEBPACK_IMPORTED_MODULE_10__.PrimeTemplate, primeng_table__WEBPACK_IMPORTED_MODULE_18__.SortableColumn, primeng_table__WEBPACK_IMPORTED_MODULE_18__.SelectableRow, primeng_table__WEBPACK_IMPORTED_MODULE_18__.SortIcon, primeng_table__WEBPACK_IMPORTED_MODULE_18__.TableCheckbox, primeng_table__WEBPACK_IMPORTED_MODULE_18__.TableHeaderCheckbox, primeng_button__WEBPACK_IMPORTED_MODULE_11__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_11__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_7__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_7__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_7__.NgModel, _instance_picker_component__WEBPACK_IMPORTED_MODULE_28__.InstancePickerComponent, _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_27__.ReviewStatusIconComponent, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_12__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_12__.ContextMenu, _series_bulk_actions_component__WEBPACK_IMPORTED_MODULE_31__.SeriesBulkActionsComponent, primeng_menu__WEBPACK_IMPORTED_MODULE_14__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_14__.Menu, primeng_progressbar__WEBPACK_IMPORTED_MODULE_15__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_15__.ProgressBar, primeng_select__WEBPACK_IMPORTED_MODULE_17__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_17__.Select, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_9__.TranslateModule, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.IconComponent, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_16__.ProgressSpinnerModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__.Tooltip, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.EllipsisTipDirective, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_23__.HeadingAreaComponent, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_9__.TranslatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.DicomDatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_24__.OrDashPipe], encapsulation: 2 }); } /***/ }, /***/ 21723 /*!**********************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/patient-library-details.facade.ts ***! \**********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PatientLibraryDetailsFacade: () => (/* binding */ PatientLibraryDetailsFacade) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../services/dicom-annotation-codec */ 19462); /* harmony import */ var _series_cache_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./series-cache.service */ 60240); /* harmony import */ var _series_cacheability__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./series-cacheability */ 54759); const FETCH_SOURCE_DESCRIPTIONS_FAILED_LOG = '[patient-library-debug] fetchSourceDescriptions failed'; function groupSeriesByUid(seriesList) { const groupsByUid = new Map(); const groups = []; for (const series of seriesList) { const seriesUid = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.normalizeSeriesUid)(series.seriesInstanceUID); if (!seriesUid) { groups.push({ series, seriesUids: [] }); continue; } const group = groupsByUid.get(seriesUid); if (group) { addSeriesUidAliases(group.seriesUids, series.seriesInstanceUID, seriesUid); continue; } const nextGroup = { series: { ...series, seriesInstanceUID: seriesUid }, seriesUids: [] }; addSeriesUidAliases(nextGroup.seriesUids, series.seriesInstanceUID, seriesUid); groupsByUid.set(seriesUid, nextGroup); groups.push(nextGroup); } return groups; } function addSeriesUidAliases(seriesUids, rawUid, normalizedUid) { const raw = String(rawUid ?? ''); for (const uid of [normalizedUid, raw]) { if (uid && !seriesUids.includes(uid)) seriesUids.push(uid); } } class PatientLibraryDetailsFacade { database = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.DicomDatabaseService); seriesCache = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_series_cache_service__WEBPACK_IMPORTED_MODULE_12__.SeriesCacheService); studyUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "studyUid" }] : [])); storeUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "storeUid" }] : [])); // Study-level instance total the caller already knows (e.g. from a study-search row), when // available. Preferred over peekStudyInstanceCount below, which exists specifically for when // this isn't available - so the peek is skipped entirely rather than run and discarded. numberOfInstancesHint = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "numberOfInstancesHint" }] : [])); seriesList$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.combineLatest)([(0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toObservable)(this.studyUid), (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toObservable)(this.storeUid)]).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_8__.switchMap)(([studyUid, storeUid]) => { if (!studyUid || !storeUid) return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.of)([]); return this.database.streamSeriesForStudy(studyUid, storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_8__.switchMap)(seriesList => { const seriesGroups = groupSeriesByUid(seriesList); if (seriesGroups.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.of)([]); const streams = seriesGroups.map(({ series, seriesUids }) => { const { modality, seriesInstanceUID: seriesUid } = series; const seriesModalityErrors = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.validateCtModality)(modality); if (!seriesUid || seriesUids.length === 0) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.of)({ ...series, cache: { cachedCount: 0, percent: 0, totalCount: 0 }, isAnnotated: false, reviewStatus: 'none', reviewStatusRank: (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.reviewStatusRank)('none'), validationErrors: seriesModalityErrors }); } this.refreshOtInstanceMetadata(modality, seriesUids, studyUid, storeUid); return (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.combineLatest)(seriesUids.map(uid => this.database.streamSeriesInstances(uid, storeUid))).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_7__.map)(documentGroups => this.buildSeriesListItem(series, documentGroups.flat()))); }); return (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.combineLatest)(streams); })); })); // True instance total across every series in the study, peeked (never cached locally) once // per study/store - see peekStudyInstanceCount. Undefined until that resolves; summary() // falls back to the series-list-derived (locally-cached-only) count until then. peekedInstanceCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "peekedInstanceCount" }] : [])); _peekRequestId = 0; // Per-series instance totals for the same study/store, keyed by seriesInstanceUID - see // peekSeriesInstanceCounts. Populates the series table's true "Images" count regardless of // what's cached locally. Unlike peekedInstanceCount above, this always runs: the study-level // hint (when present) only ever covers the study's aggregate total, never a per-series // breakdown, so there's nothing cheaper to fall back to here. peekedSeriesInstanceCounts = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(new Map(), ...(ngDevMode ? [{ debugName: "peekedSeriesInstanceCounts" }] : [])); _seriesInstanceCountsPeekRequestId = 0; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const studyUid = this.studyUid(); if (!studyUid) return; this.loadSeries(); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const studyUid = this.studyUid(); const storeUid = this.storeUid(); this.peekedInstanceCount.set(undefined); // Invalidates any in-flight peek too (via the requestId bump below) - a hint arriving // while a peek is still pending shouldn't let that peek's result overwrite it later. if (!studyUid || !storeUid || this.numberOfInstancesHint() !== undefined) { ++this._peekRequestId; return; } const requestId = ++this._peekRequestId; this.database.peekStudyInstanceCount(studyUid, storeUid).then(count => { if (requestId !== this._peekRequestId) return; this.peekedInstanceCount.set(count); }).catch(() => { // Non-fatal: leave instanceCount undefined (shown as '-') rather than surfacing an // unhandled rejection - only if this request is still the current one, so a failed // stale request can't clobber a newer request's already-resolved count. if (requestId !== this._peekRequestId) return; this.peekedInstanceCount.set(undefined); }); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const studyUid = this.studyUid(); const storeUid = this.storeUid(); this.peekedSeriesInstanceCounts.set(new Map()); if (!studyUid || !storeUid) { ++this._seriesInstanceCountsPeekRequestId; return; } const requestId = ++this._seriesInstanceCountsPeekRequestId; this.database.peekSeriesInstanceCounts(studyUid, storeUid, (seriesUid, count) => { // Series resolve out of order and one at a time - apply each as it lands rather than // waiting for the whole study to finish, so the table fills in progressively instead // of jumping from all-dashes to fully populated at once. if (requestId !== this._seriesInstanceCountsPeekRequestId) return; this.peekedSeriesInstanceCounts.update(counts => new Map(counts).set(seriesUid, count)); }).catch(() => { // Non-fatal: whatever already landed via onSeriesCount stays - only the series that // hadn't resolved yet stay at '-' rather than surfacing an unhandled rejection. }); }); } loadingData = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "loadingData" }] : [])); confirmedEmpty = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "confirmedEmpty" }] : [])); error = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "error" }] : [])); baseSeriesList = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)(this.seriesList$, { initialValue: [] }); seriesList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const list = this.baseSeriesList(); const counts = this.peekedSeriesInstanceCounts(); return list.map(series => ({ ...series, totalInstanceCount: series.seriesInstanceUID ? counts.get(series.seriesInstanceUID) : undefined })); }, ...(ngDevMode ? [{ debugName: "seriesList" }] : [])); loading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.baseSeriesList().length === 0 && (this.loadingData() || !this.confirmedEmpty()), ...(ngDevMode ? [{ debugName: "loading" }] : [])); hasAnnotatedSeries = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.baseSeriesList().some(s => s.isAnnotated), ...(ngDevMode ? [{ debugName: "hasAnnotatedSeries" }] : [])); sourceDescriptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(new Map(), ...(ngDevMode ? [{ debugName: "sourceDescriptions" }] : [])); downloadState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const storeUid = this.storeUid(); return Object.fromEntries(this.seriesCache.activeTargets().filter(target => target.storeUid === storeUid).map(target => [target.seriesUid, true])); }, ...(ngDevMode ? [{ debugName: "downloadState" }] : [])); deleteState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)({}, ...(ngDevMode ? [{ debugName: "deleteState" }] : [])); // instanceCount prefers numberOfInstancesHint (free, when the caller already has it), then // falls back to peekStudyInstanceCount's result - undefined until whichever applies resolves. // The series-list-derived count is deliberately never used as a placeholder here: it only // reflects locally-cached instances (0 for an untouched series), which is misleading rather // than genuinely "not known yet". summary = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => ({ instanceCount: this.numberOfInstancesHint() ?? this.peekedInstanceCount(), seriesCount: this.baseSeriesList().length }), ...(ngDevMode ? [{ debugName: "summary" }] : [])); _requestId = 0; /** Series whose instance metadata has already been refreshed this visit. */ otMetadataRefreshes = new Set(); /** * Review status lives in instance tags, and the local instance docs can be * missing (series never opened) or stale (a review recorded since — possibly * by another account). OT series hold only a handful of instances, so refresh * them from the store on every visit; CT series stay lazy. */ refreshOtInstanceMetadata(modality, seriesUids, studyUid, storeUid) { if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.normalizeModality)(modality) !== 'OT') return; for (const seriesUid of seriesUids) { const key = `${storeUid}:${seriesUid}`; if (this.otMetadataRefreshes.has(key)) continue; this.otMetadataRefreshes.add(key); this.database.refreshSeriesInstancesMetadata(studyUid, seriesUid, storeUid).catch(() => { // Non-fatal: the status column shows what the local cache has. }); } } buildSeriesListItem(series, documents) { const totalCount = documents.length; let cachedCount = 0; for (const document of documents) { if (document.getAttachment('pixelData')) { cachedCount += 1; } } const percent = totalCount ? Math.round(cachedCount / totalCount * 100) : 0; const reviewStatus = (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.resolveSeriesReviewStatus)(documents); return { ...series, cache: { cachedCount, percent, totalCount }, isAnnotated: (0,_series_cacheability__WEBPACK_IMPORTED_MODULE_13__.hasWorkSessionInstance)(documents), reviewStatus, reviewStatusRank: (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.reviewStatusRank)(reviewStatus), validationErrors: (0,_series_cacheability__WEBPACK_IMPORTED_MODULE_13__.resolveSeriesValidationErrors)(series.modality, documents) }; } setContext(studyUid, storeUid, numberOfInstancesHint) { this.storeUid.set(storeUid); this.studyUid.set(studyUid); this.numberOfInstancesHint.set(numberOfInstancesHint); } loadSeries() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (force = false) { const studyUid = _this.studyUid(); const storeUid = _this.storeUid(); if (!studyUid || !storeUid) return; const requestId = ++_this._requestId; _this.error.set(undefined); _this.loadingData.set(true); _this.confirmedEmpty.set(false); _this.sourceDescriptions.set(new Map()); try { if (force) { // Explicit reload: hard resync, also picking up server-side deletions. resyncSeriesForStudy // fetches before clearing, so a failed refetch leaves the existing series list in place // instead of wiping it with nothing to replace it. const remoteSeries = yield _this.database.resyncSeriesForStudy(studyUid, storeUid); if (requestId !== _this._requestId) return; _this.confirmedEmpty.set(remoteSeries.length === 0); _this.fetchSourceDescriptions(studyUid, storeUid).catch(error => { // Non-fatal: source descriptions are a supplementary label - a failure here // shouldn't surface as an error over an otherwise-successful series load. console.debug(FETCH_SOURCE_DESCRIPTIONS_FAILED_LOG, error); }); } else { yield _this.loadSeriesCacheFirst(requestId, studyUid, storeUid); } } catch (error) { if (requestId !== _this._requestId) return; _this.error.set(error.message ?? String(error)); _this.confirmedEmpty.set(true); } finally { if (requestId === _this._requestId) { _this.loadingData.set(false); } } }).apply(this, arguments); } /** Cache-first load: instant if already cached locally, revalidated in the background. */ loadSeriesCacheFirst(requestId, studyUid, storeUid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const cachedSeries = yield _this2.database.getSeriesForStudy(studyUid, storeUid); if (requestId !== _this2._requestId) return; _this2.confirmedEmpty.set(cachedSeries.length === 0); if (cachedSeries.length > 0) { // Data is already visible via the reactive stream. Revalidate in the // background so server-side changes (e.g. a newly exported OT series) // eventually surface, without blocking or clearing what's on screen. _this2.loadingData.set(false); _this2.revalidateSeriesInBackground(requestId, studyUid, storeUid); } else { _this2.fetchSourceDescriptions(studyUid, storeUid).catch(error => { // Non-fatal: source descriptions are a supplementary label - a failure here // shouldn't surface as an error over an otherwise-successful series load. console.debug(FETCH_SOURCE_DESCRIPTIONS_FAILED_LOG, error); }); } })(); } revalidateSeriesInBackground(requestId, studyUid, storeUid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { yield _this3.database.refreshSeriesForStudy(studyUid, storeUid, () => requestId === _this3._requestId); if (requestId !== _this3._requestId) return; _this3.fetchSourceDescriptions(studyUid, storeUid).catch(error => { // Non-fatal: source descriptions are a supplementary label - a failure here // shouldn't surface as an error over an otherwise-successful series load. console.debug(FETCH_SOURCE_DESCRIPTIONS_FAILED_LOG, error); }); } catch { // Non-fatal: keep showing the already-cached series list. } })(); } fetchSourceDescriptions(studyUid, storeUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const series = yield _this4.database.getSeriesForStudy(studyUid, storeUid); const otSeries = series.filter(s => String(s.modality ?? '').trim().toUpperCase() === 'OT' && s.seriesInstanceUID); if (otSeries.length === 0) return; const descriptions = new Map(); for (const s of otSeries) { const seriesUid = s.seriesInstanceUID ?? ''; try { // Local-only: reads whatever's already cached instead of fetching the series just to // compute this label - callers that need the data itself still fetch it explicitly. const instances = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.firstValueFrom)(_this4.database.streamSeriesInstances(seriesUid, storeUid)); if (instances.length === 0) continue; const typed = instances; const meta = typed[0]?.toJSON().metadata; if (String(meta?.['00080070']?.Value?.[0] ?? '').trim() !== 'Tomoverse Imaging') continue; const desc = yield _this4.findSourceDescription(typed, storeUid); if (desc) descriptions.set(seriesUid, desc); } catch { // Non-fatal: binary may not be available yet } } _this4.sourceDescriptions.set(descriptions); })(); } findSourceDescription(instances, storeUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { for (const inst of instances) { const binary = yield _this5.database.getCachedBinary(inst.sopInstanceUID, storeUid); if (!binary) continue; const desc = (0,_services_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_11__.extractAnnotationTags)(binary)?.sourceSeriesDescription ?? ''; if (desc) return desc; } return ''; })(); } isDownloading(seriesUid) { return Boolean(this.downloadState()[seriesUid]); } isDeleting(seriesUid) { return Boolean(this.deleteState()[seriesUid]); } downloadSeries(seriesUid) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this6.downloadSeriesBatch([seriesUid]); })(); } downloadSeriesBatch(seriesUids, detail) { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const studyUid = _this7.studyUid(); const storeUid = _this7.storeUid(); const targets = seriesUids.filter(Boolean); const [first] = targets; if (!studyUid || !storeUid || !first) return; try { yield _this7.seriesCache.cache(targets.map(seriesUid => ({ seriesUid, storeUid, studyUid })), detail ?? _this7.seriesLabel(first)); // Binaries just became available - recompute source descriptions now instead of waiting // for an unrelated series reload to happen to pick them up. _this7.fetchSourceDescriptions(studyUid, storeUid).catch(error => { // Non-fatal: source descriptions are a supplementary label - a failure here // shouldn't surface as an error over an otherwise-successful download. console.debug(FETCH_SOURCE_DESCRIPTIONS_FAILED_LOG, error); }); } catch (error) { _this7.error.set(error.message ?? String(error)); } })(); } seriesLabel(seriesUid) { const series = this.baseSeriesList().find(item => item.seriesInstanceUID === seriesUid); const description = series?.seriesDescription?.trim() || (series?.seriesNumber === undefined ? seriesUid : `#${series.seriesNumber}`); const patient = series?.patientName?.trim(); return patient ? `${patient} · ${description}` : description; } deleteSeries(seriesUid) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const storeUid = _this8.storeUid(); if (!seriesUid || !storeUid) return; _this8.setDeleteState(seriesUid, true); try { yield _this8.database.deleteSeriesCache(seriesUid, storeUid); } catch (error) { _this8.error.set(error.message ?? String(error)); } finally { _this8.setDeleteState(seriesUid, false); } })(); } setDeleteState(seriesUid, isDeleting) { this.deleteState.update(state => ({ ...state, [seriesUid]: isDeleting })); } static ɵfac = function PatientLibraryDetailsFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PatientLibraryDetailsFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: PatientLibraryDetailsFacade, factory: PatientLibraryDetailsFacade.ɵfac }); } /***/ }, /***/ 33784 /*!**********************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/patient-library-list.component.ts ***! \**********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PatientLibraryListComponent: () => (/* binding */ PatientLibraryListComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 57168); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_datepicker__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/datepicker */ 83203); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_multiselect__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/multiselect */ 58612); /* harmony import */ var primeng_paginator__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/paginator */ 69130); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../review-status-icon/review-status-icon.component */ 92729); /* harmony import */ var _patient_library_list_facade__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./patient-library-list.facade */ 67045); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ cap: a0 }); const _c1 = () => ({ "table-layout": "fixed" }); const _c2 = a0 => ({ count: a0 }); function PatientLibraryListComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", ctx_r0.error(), " "); } } function PatientLibraryListComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind2"](2, 1, "patientList.truncated", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction1"](4, _c0, ctx_r0.total())), " "); } } function PatientLibraryListComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](2, 1, "patientList.noStores"), " "); } } function PatientLibraryListComponent_Conditional_4_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "tr")(1, "th", 20)(2, "span", 21)(3, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](6, "p-sortIcon", 23); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](7, "th", 24)(8, "span", 21)(9, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](12, "p-sortIcon", 25); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](13, "th", 26)(14, "span", 21)(15, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](16); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](17, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](18, "p-sortIcon", 27); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](19, "th", 28)(20, "span", 21)(21, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](23, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](24, "p-sortIcon", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](25, "th", 30); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](26); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](27, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](28, "th", 31)(29, "span", 21)(30, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](31); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](32, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](33, "p-sortIcon", 32); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](34, "th", 33)(35, "span", 34)(36, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](38, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](39, "p-sortIcon", 35); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](40, "th", 36)(41, "span", 34)(42, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](43); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](44, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](45, "p-sortIcon", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](46, "th", 38); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](47); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](48, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](49, "th", 39)(50, "span", 34)(51, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](52); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](53, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](54, "p-sortIcon", 40); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](55, "th", 41); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](56); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](57, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](58, "tr", 42)(59, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](60, "input", 43); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](61, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](62, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](63, "input", 44); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](64, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](65, "th")(66, "div", 45); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](67, "p-datepicker", 46); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](68, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](69, "p-datepicker", 47); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](70, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](71, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](72, "input", 48); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](73, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](74, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](75, "p-multiselect", 49); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](76, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](77, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](78, "input", 50); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](79, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](80, "th")(81, "th")(82, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](83, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](84, "p-select", 51); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](85, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](86, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](5, 26, "patientList.table.patientName")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](11, 28, "patientList.table.mrn")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](17, 30, "patientList.table.studyDate")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](23, 32, "patientList.table.description")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](27, 34, "patientList.table.modalities"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](32, 36, "patientList.table.institution")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](38, 38, "patientList.table.series")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](44, 40, "patientList.table.sessions")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](48, 42, "patientList.table.annotated"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](53, 44, "patientList.table.reviewed")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](57, 46, "patientList.table.actions"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formGroup", ctx_r0.filterForm); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](61, 48, "patientList.filters.patientName")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](64, 50, "patientList.filters.mrn")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("showIcon", true)("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](68, 52, "patientList.filters.dateFrom")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("showIcon", true)("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](70, 54, "patientList.filters.dateTo")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](73, 56, "patientList.filters.description")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("options", ctx_r0.modalityOptions)("showToggleAll", false)("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](76, 58, "patientList.filters.modality")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](79, 60, "patientList.filters.institution")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("options", ctx_r0.statusFilterOptions())("showClear", true)("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](85, 62, "reviewStatus.all")); } } function PatientLibraryListComponent_Conditional_4_ng_template_3_Conditional_37_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "span", 56); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](1, "lib-icon", 63); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } } function PatientLibraryListComponent_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](1, "tr", 52); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("contextmenu", function PatientLibraryListComponent_Conditional_4_ng_template_3_Template_tr_contextmenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const study_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreadContextLet"](0); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); const studyMenuContext_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](9); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.studyMenu.openAtPointer(studyMenuContext_r5, $event, study_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](2, "td", 53, 5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](4, "dicomPersonName"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](6, "dicomPersonName"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](7, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](8, "td", 53, 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](11, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](12, "td", 53, 7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](14, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](15); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](16, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](17, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](18, "td", 53, 8); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](20); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](21, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](22, "td", 54, 9); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](25, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](26, "td", 53, 10); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](28); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](29, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](30, "td", 55); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](31); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](32, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](33, "td", 55); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](34); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](35, "orDash"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](36, "td", 55); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](37, PatientLibraryListComponent_Conditional_4_ng_template_3_Conditional_37_Template, 2, 0, "span", 56); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](38, "td", 55); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](39, "lib-review-status-icon", 57); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](40, "td")(41, "div", 58)(42, "p-button", 59); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](43, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function PatientLibraryListComponent_Conditional_4_ng_template_3_Template_p_button_click_42_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const study_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreadContextLet"](0); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); const studyMenuPopup_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](7); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.studyMenu.openFromButton(studyMenuPopup_r6, $event, study_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](44, "lib-icon", 60); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](45, "p-button", 61); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](46, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](47, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function PatientLibraryListComponent_Conditional_4_ng_template_3_Template_p_button_click_45_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const study_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreadContextLet"](0); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.selectStudy(study_r4.studyInstanceUID)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](48, "lib-icon", 62); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const rawStudy_r7 = ctx.$implicit; const patientNameTip_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](3); const patientIdTip_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](9); const studyDateTip_r10 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](13); const descriptionTip_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](19); const modalitiesTip_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](23); const institutionTip_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](27); const study_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵstoreLet"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2).asStudy(rawStudy_r7)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pSelectableRow", study_r14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", patientNameTip_r8.truncated() ? _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](4, 21, study_r14.patientName) : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](7, 25, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](6, 23, study_r14.patientName)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", patientIdTip_r9.truncated() ? study_r14.patientID : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](11, 27, study_r14.patientID), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", studyDateTip_r10.truncated() ? _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind3"](14, 29, study_r14.studyDate, !!study_r14.studyTime, study_r14.studyTime) : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](17, 37, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind3"](16, 33, study_r14.studyDate, !!study_r14.studyTime, study_r14.studyTime)), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", descriptionTip_r11.truncated() ? study_r14.studyDescription : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](21, 39, study_r14.studyDescription), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", modalitiesTip_r12.truncated() ? study_r14.modalities.join(", ") : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](25, 41, study_r14.modalities.join(", ")), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", institutionTip_r13.truncated() ? study_r14.institutionName : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](29, 43, study_r14.institutionName), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](32, 45, study_r14.numberOfSeries)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](35, 47, study_r14.workSessionCount)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](study_r14.isAnnotated ? 37 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("status", study_r14.reviewStatus ?? "none"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](43, 49, "patientList.table.actions")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](46, 51, "patientList.open"))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](47, 53, "patientList.open")); } } function PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](1, 1, "patientList.loading"), " "); } } function PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](1, 1, "patientList.noMatches"), " "); } } function PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](1, 1, "patientList.noData"), " "); } } function PatientLibraryListComponent_Conditional_4_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "tr")(1, "td", 55); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](2, PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_2_Template, 2, 3)(3, PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_3_Template, 2, 3)(4, PatientLibraryListComponent_Conditional_4_ng_template_5_Conditional_4_Template, 2, 3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵattribute"]("colspan", 11); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx_r0.loading() ? 2 : ctx_r0.hasActiveFilters() ? 3 : 4); } } function PatientLibraryListComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "p-table", 19); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("onLazyLoad", function PatientLibraryListComponent_Conditional_4_Template_p_table_onLazyLoad_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.onLazyLoad($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayListener"]("selectionChange", function PatientLibraryListComponent_Conditional_4_Template_p_table_selectionChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayBindingSet"](ctx_r0.rowClickedStudyUid, $event) || (ctx_r0.rowClickedStudyUid = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("onRowSelect", function PatientLibraryListComponent_Conditional_4_Template_p_table_onRowSelect_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.onRowSelect($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplate"](1, PatientLibraryListComponent_Conditional_4_ng_template_1_Template, 87, 64, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplateRefExtractor"])(3, PatientLibraryListComponent_Conditional_4_ng_template_3_Template, 49, 55, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplateRefExtractor"])(5, PatientLibraryListComponent_Conditional_4_ng_template_5_Template, 5, 2, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("value", ctx_r0.rows())("loading", ctx_r0.loading())("lazy", true)("sortField", ctx_r0.sortField())("sortOrder", ctx_r0.sortOrder())("paginator", false)("tableStyle", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction0"](9, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayProperty"]("selection", ctx_r0.rowClickedStudyUid); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("metaKeySelection", true); } } function PatientLibraryListComponent_Conditional_5_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1, "\u00B7"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind2"](4, 1, "patientList.counts.series", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction1"](4, _c2, ctx_r0.summary().seriesCount))); } } function PatientLibraryListComponent_Conditional_5_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1, "\u00B7"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind2"](4, 1, "patientList.counts.instances", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction1"](4, _c2, ctx_r0.summary().instanceCount)), " "); } } function PatientLibraryListComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { const _r15 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 16)(1, "div", 64)(2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](5, PatientLibraryListComponent_Conditional_5_Conditional_5_Template, 5, 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](6, PatientLibraryListComponent_Conditional_5_Conditional_6_Template, 5, 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](7, "span", 65); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](10, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](11, "p-select", 66); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("ngModelChange", function PatientLibraryListComponent_Conditional_5_Template_p_select_ngModelChange_11_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r15); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.onRowsPerPageChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](12, "span", 65); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](13); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](14, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](15, "p-paginator", 67); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("onPageChange", function PatientLibraryListComponent_Conditional_5_Template_p_paginator_onPageChange_15_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r15); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.onPageChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind2"](4, 16, "patientList.counts.studies", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction1"](23, _c2, ctx_r0.summary().studyCount))); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx_r0.summary().seriesCount !== undefined ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx_r0.summary().instanceCount !== undefined ? 6 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](9, 19, "patientList.pagination.rowsPerPage")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("options", ctx_r0.pageSizeOptions)("ngModel", ctx_r0.pageSize()); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate4"](" ", ctx_r0.firstRecord(), "-", ctx_r0.lastRecord(), " ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](14, 21, "patientList.pagination.of"), " ", ctx_r0.total(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("showCurrentPageReport", false)("showPageLinks", false)("showFirstLastIcon", false)("first", ctx_r0.first())("rows", ctx_r0.pageSize())("totalRecords", ctx_r0.total()); } } const FILTER_DEBOUNCE_MS = 250; class PatientLibraryListComponent { vm = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_21__.PatientLibraryListFacade); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__.TranslateService); studySelected = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.EventEmitter(); studyMenu = new _tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__.RowMenuController(study => this.buildStudyMenuItems(study)); rowClickedStudyUid = undefined; lastClickedStudyUid = undefined; lastClickAtMs = 0; doubleClickThresholdMs = 300; loading = this.vm.loading; error = this.vm.error; rows = this.vm.rows; total = this.vm.total; truncated = this.vm.truncated; summary = this.vm.summary; pageSize = this.vm.pageSize; first = this.vm.first; hasActiveFilters = this.vm.hasActiveFilters; stores = this.vm.stores; loadingStores = this.vm.loadingStores; selectedStoreUid = this.vm.selectedStoreUid; pageSizeOptions = [12, 25, 50]; modalityOptions = [..._tomoverse_dtos__WEBPACK_IMPORTED_MODULE_17__.MODALITY_OPTIONS]; langChange = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)(this.translate.onLangChange); statusFilterOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this.langChange(); return ['approved', 'rejected', 'unapproved'].map(value => ({ label: this.translate.instant(`reviewStatus.${value}`), value })); }, ...(ngDevMode ? [{ debugName: "statusFilterOptions" }] : [])); firstRecord = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.total() === 0 ? 0 : this.first() + 1, ...(ngDevMode ? [{ debugName: "firstRecord" }] : [])); lastRecord = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => Math.min(this.first() + this.pageSize(), this.total()), ...(ngDevMode ? [{ debugName: "lastRecord" }] : [])); sortField = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.vm.sortSpec()?.field, ...(ngDevMode ? [{ debugName: "sortField" }] : [])); sortOrder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.vm.sortSpec()?.direction ?? _tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__.PRIMENG_DEFAULT_SORT_ORDER, ...(ngDevMode ? [{ debugName: "sortOrder" }] : [])); filterForm = new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormGroup({ description: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl('', { nonNullable: true }), institution: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl('', { nonNullable: true }), modalities: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl([], { nonNullable: true }), mrn: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl('', { nonNullable: true }), patientName: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl('', { nonNullable: true }), reviewStatus: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl(undefined, { nonNullable: true }), studyDateFrom: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl(undefined, { nonNullable: true }), studyDateTo: new _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControl(undefined, { nonNullable: true }) }); constructor() { this.hydrateFormFromCriteria(); this.filterForm.valueChanges.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.debounceTime)(FILTER_DEBOUNCE_MS), (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.takeUntilDestroyed)()).subscribe(() => this.vm.setCriteria(this.buildCriteria())); this.vm.clearFiltersRequests.pipe((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.takeUntilDestroyed)()).subscribe(() => this.clearFilters()); } hydrateFormFromCriteria() { const { description, institution, modalities, patientID, patientName, reviewStatus, studyDateFrom, studyDateTo } = this.vm.criteria(); this.filterForm.reset({ description: description ?? '', institution: institution ?? '', modalities: modalities ?? [], mrn: patientID ?? '', patientName: patientName ?? '', reviewStatus, studyDateFrom: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.parseDicomDate)(studyDateFrom), studyDateTo: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.parseDicomDate)(studyDateTo) }, { emitEvent: false }); } onLazyLoad(event) { const field = typeof event.sortField === 'string' ? event.sortField : undefined; const sort = field ? { direction: event.sortOrder ?? 1, field } : undefined; const current = this.vm.sortSpec(); if (sort?.field === current?.field && sort?.direction === current?.direction) return; this.vm.applySort(sort); } onPageChange(event) { this.vm.setPage(event.first ?? 0, event.rows ?? this.pageSize()); } onRowsPerPageChange(rows) { this.vm.setPage(0, rows); } buildCriteria() { const { description, institution, modalities, mrn, patientName, reviewStatus, studyDateFrom, studyDateTo } = this.filterForm.getRawValue(); const criteria = {}; if (modalities.length > 0) criteria.modalities = modalities; if (reviewStatus) criteria.reviewStatus = reviewStatus; const textFields = [['description', description], ['institution', institution], ['patientID', mrn], ['patientName', patientName]]; for (const [key, raw] of textFields) { const term = raw.trim(); if (term) criteria[key] = term; } if (studyDateFrom) criteria.studyDateFrom = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.toDicomDate)(studyDateFrom); if (studyDateTo) criteria.studyDateTo = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.toDicomDate)(studyDateTo); return criteria; } clearFilters() { this.filterForm.reset({ description: '', institution: '', modalities: [], mrn: '', patientName: '', reviewStatus: undefined, studyDateFrom: undefined, studyDateTo: undefined }); } reloadStudies() { this.vm.reloadStudies(); } onRowSelect(event) { const study = Array.isArray(event?.data) ? event.data[0] : event?.data; const { studyInstanceUID } = study || {}; const now = Date.now(); const isDoubleClick = studyInstanceUID !== undefined && studyInstanceUID === this.lastClickedStudyUid && now - this.lastClickAtMs <= this.doubleClickThresholdMs; if (isDoubleClick) { this.lastClickedStudyUid = undefined; this.lastClickAtMs = 0; this.selectStudy(studyInstanceUID, false, study?.numberOfInstances); return; } this.lastClickedStudyUid = studyInstanceUID; this.lastClickAtMs = now; } asStudy(value) { return value; } selectStudy(studyUID, cacheAll = false, numberOfInstances) { const storeUid = this.selectedStoreUid(); if (studyUID && storeUid) { this.studySelected.emit({ cacheAll, numberOfInstances, storeUid, studyUid: studyUID }); } } /** * The viewer opens CT, plus OT when the series is a tvCT analysis - plain OT is not * viewable, and `isAnnotated` is the only per-study signal for that. Instance-level * validation can still reject a CT series, so this rules studies out but never in. */ hasCacheableModality(study) { return (study.modalities ?? []).some(modality => { const viewable = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.isViewableModality)(modality); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.normalizeModality)(modality) === 'OT' ? viewable && study.isAnnotated : viewable; }); } /** * Caching happens in the series view, so the user can watch per-series progress. Only * go there when there is something to fetch: the modalities on the row rule out studies * the viewer cannot open at all, and the local database rules out ones already cached. */ cacheStudy(study) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const studyUid = study.studyInstanceUID; const storeUid = _this.selectedStoreUid(); if (!studyUid || !storeUid) return; if (yield _this.vm.hasCacheableSeries(studyUid, storeUid)) { _this.selectStudy(studyUid, true, study.numberOfInstances); return; } _this.vm.notifyNothingToCache(); })(); } buildStudyMenuItems(study) { const studyUid = study.studyInstanceUID; return [{ command: () => this.selectStudy(studyUid, false, study.numberOfInstances), disabled: !studyUid, icon: 'pi pi-folder-open', label: this.translate.instant('patientList.menu.openStudy') }, { separator: true }, { command: () => this.cacheStudy(study), disabled: !studyUid || !this.hasCacheableModality(study), icon: 'pi pi-cloud-download', label: this.translate.instant('patientList.menu.cache') }, { separator: true }, (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__.dangerMenuItem)({ disabled: true, icon: 'pi pi-trash', label: this.translate.instant('patientList.menu.deleteStudy') })]; } static ɵfac = function PatientLibraryListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PatientLibraryListComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵdefineComponent"]({ type: PatientLibraryListComponent, selectors: [["lib-patient-library-list"]], hostAttrs: [1, "flex", "h-full", "flex-col"], outputs: { studySelected: "studySelected" }, decls: 10, vars: 7, consts: [["studyMenuPopup", ""], ["studyMenuContext", ""], ["header", ""], ["body", ""], ["emptymessage", ""], ["patientNameTip", "libEllipsisTip"], ["patientIdTip", "libEllipsisTip"], ["studyDateTip", "libEllipsisTip"], ["descriptionTip", "libEllipsisTip"], ["modalitiesTip", "libEllipsisTip"], ["institutionTip", "libEllipsisTip"], [1, "flex", "min-h-0", "flex-1", "flex-col"], [1, "border-destructive/30", "bg-destructive/10", "text-destructive", "mx-4", "mb-4", "shrink-0", "rounded-md", "border", "px-3", "py-2"], ["data-test-id", "patient-library-div-truncated", 1, "border-primary-500/40", "bg-primary-500/10", "text-primary-400", "mx-4", "mb-4", "shrink-0", "rounded-md", "border", "px-3", "py-2", "text-sm"], [1, "text-muted-color", "bw", "mx-4", "mb-4", "shrink-0", "rounded-md", "border", "px-3", "py-2"], ["dataKey", "studyInstanceUID", "selectionMode", "single", "scrollable", "", "scrollHeight", "flex", 1, "library-table", "min-h-0", "flex-1", 3, "value", "loading", "lazy", "sortField", "sortOrder", "paginator", "tableStyle", "selection", "metaKeySelection"], [1, "library-footer", "text-muted-color", "border-surface-800", "flex", "shrink-0", "items-center", "justify-end", "gap-3", "border-t", "px-8", "py-2", "text-sm"], ["data-test-id", "patient-library-p-menu-study", "popup", "", "appendTo", "body", 3, "model"], ["data-test-id", "patient-library-p-contextmenu-study", "appendTo", "body", 3, "model"], ["dataKey", "studyInstanceUID", "selectionMode", "single", "scrollable", "", "scrollHeight", "flex", 1, "library-table", "min-h-0", "flex-1", 3, "onLazyLoad", "selectionChange", "onRowSelect", "value", "loading", "lazy", "sortField", "sortOrder", "paginator", "tableStyle", "selection", "metaKeySelection"], ["pSortableColumn", "patientName", 1, "w-[10.3125rem]", "overflow-hidden"], [1, "flex", "min-w-0", "items-center", "gap-1"], [1, "truncate"], ["field", "patientName"], ["pSortableColumn", "patientID", 1, "w-[7.5rem]", "overflow-hidden"], ["field", "patientID"], ["pSortableColumn", "studyDate", 1, "w-[18.125rem]", "overflow-hidden"], ["field", "studyDate"], ["pSortableColumn", "studyDescription", 1, "w-[13.75rem]", "overflow-hidden"], ["field", "studyDescription"], [1, "w-[9.0625rem]", "overflow-hidden", "text-center", "whitespace-nowrap"], ["pSortableColumn", "institutionName", 1, "w-[8.75rem]", "overflow-hidden"], ["field", "institutionName"], ["pSortableColumn", "numberOfSeries", 1, "w-[5.9375rem]", "overflow-hidden", "text-center"], [1, "flex", "min-w-0", "items-center", "justify-center", "gap-1"], ["field", "numberOfSeries"], ["pSortableColumn", "workSessionCount", 1, "w-[6.875rem]", "overflow-hidden", "text-center"], ["field", "workSessionCount"], [1, "w-[6.875rem]", "overflow-hidden", "text-center", "whitespace-nowrap"], ["pSortableColumn", "reviewStatusRank", 1, "w-[6.25rem]", "overflow-hidden", "text-center"], ["field", "reviewStatusRank"], [1, "w-[7.8125rem]", "overflow-hidden", "text-right", "whitespace-nowrap"], [3, "formGroup"], ["pInputText", "", "pSize", "small", "type", "text", "formControlName", "patientName", "data-test-id", "patient-library-input-filter-patient-name", 1, "w-full", 3, "placeholder"], ["pInputText", "", "pSize", "small", "type", "text", "formControlName", "mrn", "data-test-id", "patient-library-input-filter-mrn", 1, "w-full", 3, "placeholder"], [1, "flex", "items-center", "gap-1"], ["formControlName", "studyDateFrom", "dateFormat", "dd.mm.yy", "size", "small", "appendTo", "body", "iconDisplay", "input", "styleClass", "w-full", "data-test-id", "patient-library-p-datepicker-filter-date-from", 3, "showIcon", "placeholder"], ["formControlName", "studyDateTo", "dateFormat", "dd.mm.yy", "size", "small", "appendTo", "body", "iconDisplay", "input", "styleClass", "w-full", "data-test-id", "patient-library-p-datepicker-filter-date-to", 3, "showIcon", "placeholder"], ["pInputText", "", "pSize", "small", "type", "text", "formControlName", "description", "data-test-id", "patient-library-input-filter-description", 1, "w-full", 3, "placeholder"], ["formControlName", "modalities", "size", "small", "appendTo", "body", "styleClass", "w-full", "data-test-id", "patient-library-p-multiselect-filter-study-modality", 3, "options", "showToggleAll", "placeholder"], ["pInputText", "", "pSize", "small", "type", "text", "formControlName", "institution", "data-test-id", "patient-library-input-filter-institution", 1, "w-full", 3, "placeholder"], ["formControlName", "reviewStatus", "optionLabel", "label", "optionValue", "value", "size", "small", "appendTo", "body", "styleClass", "w-full", "data-test-id", "patient-library-p-select-filter-review-status", 3, "options", "showClear", "placeholder"], [3, "contextmenu", "pSelectableRow"], ["libEllipsisTip", "", "tooltipPosition", "top", 3, "pTooltip"], ["libEllipsisTip", "", "tooltipPosition", "top", 1, "text-center", 3, "pTooltip"], [1, "text-center"], [1, "text-(--p-app-status-success)"], [3, "status"], [1, "flex", "items-center", "justify-end", "gap-2"], ["data-test-id", "patient-library-p-button-study-menu", "severity", "secondary", "text", "", "size", "small", 3, "click", "ariaLabel"], ["icon", "ellipsis-v"], ["data-test-id", "patient-library-p-button-open-study", "severity", "secondary", "rounded", "", "text", "", "size", "small", "styleClass", "h-[30px] w-[30px] p-0", "tooltipPosition", "top", 3, "click", "ariaLabel", "pTooltip"], ["icon", "arrow-right", 1, "size-(--p-app-icon-size-xs)"], ["icon", "check"], ["data-test-id", "patient-library-div-summary", 1, "mr-auto", "flex", "items-center", "gap-2"], [1, "shrink-0"], ["data-test-id", "patient-library-p-select-page-size", "size", "small", "appendTo", "body", 1, "overflow-hidden", 3, "ngModelChange", "options", "ngModel"], ["data-test-id", "patient-library-p-paginator-nav", 1, "gap-3", "bg-transparent", "p-0", 3, "onPageChange", "showCurrentPageReport", "showPageLinks", "showFirstLastIcon", "first", "rows", "totalRecords"]], template: function PatientLibraryListComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](1, PatientLibraryListComponent_Conditional_1_Template, 2, 1, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](2, PatientLibraryListComponent_Conditional_2_Template, 3, 6, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](3, PatientLibraryListComponent_Conditional_3_Template, 3, 3, "div", 14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](4, PatientLibraryListComponent_Conditional_4_Template, 7, 10, "p-table", 15); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](5, PatientLibraryListComponent_Conditional_5_Template, 16, 25, "div", 16); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](6, "p-menu", 17, 0)(8, "p-contextmenu", 18, 1); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx.error() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx.truncated() ? 2 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](!ctx.loading() && !ctx.loadingStores() && ctx.stores().length === 0 ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx.stores().length !== 0 ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](!ctx.loading() && ctx.stores().length !== 0 ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("model", ctx.studyMenu.items()); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("model", ctx.studyMenu.items()); } }, dependencies: [primeng_table__WEBPACK_IMPORTED_MODULE_15__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_15__.Table, primeng_table__WEBPACK_IMPORTED_MODULE_15__.SortableColumn, primeng_table__WEBPACK_IMPORTED_MODULE_15__.SelectableRow, primeng_table__WEBPACK_IMPORTED_MODULE_15__.SortIcon, primeng_button__WEBPACK_IMPORTED_MODULE_7__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_7__.Button, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_8__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_8__.ContextMenu, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__.TranslateModule, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgControlStatusGroup, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgModel, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormGroupDirective, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormControlName, primeng_datepicker__WEBPACK_IMPORTED_MODULE_9__.DatePickerModule, primeng_datepicker__WEBPACK_IMPORTED_MODULE_9__.DatePicker, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputText, primeng_menu__WEBPACK_IMPORTED_MODULE_11__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_11__.Menu, primeng_multiselect__WEBPACK_IMPORTED_MODULE_12__.MultiSelectModule, primeng_multiselect__WEBPACK_IMPORTED_MODULE_12__.MultiSelect, primeng_select__WEBPACK_IMPORTED_MODULE_14__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_14__.Select, primeng_paginator__WEBPACK_IMPORTED_MODULE_13__.PaginatorModule, primeng_paginator__WEBPACK_IMPORTED_MODULE_13__.Paginator, primeng_tooltip__WEBPACK_IMPORTED_MODULE_16__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_16__.Tooltip, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__.EllipsisTipDirective, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_18__.IconComponent, _review_status_icon_review_status_icon_component__WEBPACK_IMPORTED_MODULE_20__.ReviewStatusIconComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__.TranslatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.DicomDatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.DicomPersonNamePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_19__.OrDashPipe], encapsulation: 2 }); } /***/ }, /***/ 67045 /*!*******************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/patient-library-list.facade.ts ***! \*******************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PatientLibraryListFacade: () => (/* binding */ PatientLibraryListFacade) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 33242); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 90015); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 45541); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _series_cacheability__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./series-cacheability */ 54759); const EMPTY_PAGE = { aggregates: {}, rows: [], total: 0, truncated: false }; function statusMapsEqual(a, b) { if (a.size !== b.size) return false; for (const [studyUid, status] of a) { if (b.get(studyUid) !== status) return false; } return true; } class PatientLibraryListFacade { provider = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_12__.StudySearchProvider); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_12__.DicomStoreListService); preferences = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_12__.PreferencesService); database = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_12__.DicomDatabaseService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_11__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__.TranslateService); loading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "loading" }] : [])); error = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "error" }] : [])); page = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(EMPTY_PAGE, ...(ngDevMode ? [{ debugName: "page" }] : [])); criteria = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)({}, ...(ngDevMode ? [{ debugName: "criteria" }] : [])); sortSpec = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "sortSpec" }] : [])); first = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "first" }] : [])); pageSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(12, ...(ngDevMode ? [{ debugName: "pageSize" }] : [])); stores = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "stores" }] : [])); selectedStoreUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "selectedStoreUid" }] : [])); loadingStores = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "loadingStores" }] : [])); storeStats = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "storeStats" }] : [])); /** Review status per studyUid, from locally cached OT instance metadata (fills in as studies are visited). */ reviewStatuses = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(new Map(), ...(ngDevMode ? [{ debugName: "reviewStatuses" }] : [])); rows = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.page().rows, ...(ngDevMode ? [{ debugName: "rows" }] : [])); total = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.page().total, ...(ngDevMode ? [{ debugName: "total" }] : [])); truncated = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.page().truncated, ...(ngDevMode ? [{ debugName: "truncated" }] : [])); summary = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { aggregates, total } = this.page(); return { instanceCount: aggregates.instanceSum, seriesCount: aggregates.seriesSum, studyCount: total }; }, ...(ngDevMode ? [{ debugName: "summary" }] : [])); hasActiveFilters = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => Object.keys(this.criteria()).length > 0, ...(ngDevMode ? [{ debugName: "hasActiveFilters" }] : [])); clearFilters$ = new rxjs__WEBPACK_IMPORTED_MODULE_4__.Subject(); clearFiltersRequests = this.clearFilters$.asObservable(); /** Set while the details (series) view is open; undefined on the study list. */ detailsToolbar = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "detailsToolbar" }] : [])); query$ = new rxjs__WEBPACK_IMPORTED_MODULE_4__.Subject(); constructor() { this.query$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.tap)(() => { this.loading.set(true); this.error.set(undefined); }), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.switchMap)(query => this.provider.search(query).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_7__.catchError)(error => { this.error.set(error.message ?? String(error)); this.loading.set(false); return rxjs__WEBPACK_IMPORTED_MODULE_6__.EMPTY; }))), (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.takeUntilDestroyed)()).subscribe(page => { this.page.set(page); this.loading.set(false); this.refreshReviewStatuses(page.rows); }); } /** Overlay the Reviewed column for the displayed rows (store-resolved); non-blocking, best-effort. */ refreshReviewStatuses(rows) { const storeUid = this.selectedStoreUid(); if (!storeUid) return; const otStudyUids = rows.filter(row => row.modalities.some(modality => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.normalizeModality)(modality) === 'OT')).map(row => row.studyInstanceUID); if (otStudyUids.length === 0) return; this.database.getStudyOtReviewStatuses(otStudyUids, storeUid).then(statuses => { // Merge: keep statuses gathered on other pages so filtering and sorting see them. const merged = new Map([...this.reviewStatuses(), ...statuses]); if (statusMapsEqual(merged, this.reviewStatuses())) return; this.reviewStatuses.set(merged); this.runSearch(); }).catch(() => { // Non-fatal: the column simply stays blank. }); } init() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this.loadStores(); _this.runSearch(); })(); } loadStores() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this2.loadingStores.set(true); try { const stores = yield _this2.storeList.getReachableStores(); _this2.stores.set(stores); const persisted = _this2.preferences.get().storeUid; const defaultStore = stores.find(store => store.uid === persisted) ?? stores[0]; _this2.selectedStoreUid.set(defaultStore?.uid); if (stores.length === 0) { yield _this2.warnIfConfiguredStoresUnreachable(); } } catch (error) { _this2.error.set(error.message ?? String(error)); } finally { _this2.loadingStores.set(false); } })(); } /** * Distinguishes "no DICOM stores configured" (covered by the empty-state banner) from * "stores are configured but none responded to a ping" — the latter warrants a toast * since it usually means bad credentials or an unreachable store instance. */ warnIfConfiguredStoresUnreachable() { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const enabled = yield _this3.storeList.getEnabledStores(); if (enabled.length === 0) return; _this3.messageService.add({ detail: _this3.translate.instant('dicomImporter.storesUnreachable.detail'), life: 8000, severity: 'error', summary: _this3.translate.instant('dicomImporter.storesUnreachable.summary') }); })(); } /** * Whether caching the study would pull anything down, judged from the local database * with the same per-series rule the series view applies. Anything not stored locally * yet cannot be ruled out and counts as cacheable, so a study opened for the first * time always goes through. */ hasCacheableSeries(studyUid, storeUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const series = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.firstValueFrom)(_this4.database.streamSeriesForStudy(studyUid, storeUid)); if (series.length === 0) return true; for (const { modality, seriesInstanceUID: seriesUid } of series) { if (!seriesUid || !(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.isViewableModality)(modality)) continue; const documents = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.firstValueFrom)(_this4.database.streamSeriesInstances(seriesUid, storeUid)); if (documents.length === 0) return true; const cachedCount = documents.filter(d => d.getAttachment('pixelData')).length; if (cachedCount === documents.length) continue; if ((0,_series_cacheability__WEBPACK_IMPORTED_MODULE_14__.resolveSeriesValidationErrors)(modality, documents).length > 0) continue; return true; } return false; })(); } notifyNothingToCache() { this.messageService.add({ detail: this.translate.instant('patientList.nothingToCache.detail'), life: 5000, severity: 'info', summary: this.translate.instant('patientList.nothingToCache.summary') }); } /** Switch store: persist it, keep filters/sort, reset to page 1, re-search. */ selectStore(storeUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (storeUid === _this5.selectedStoreUid()) return; _this5.selectedStoreUid.set(storeUid); _this5.preferences.patch({ storeUid }); _this5.storeStats.set(undefined); _this5.reviewStatuses.set(new Map()); _this5.first.set(0); _this5.runSearch(); })(); } requestClearFilters() { this.clearFilters$.next(); } loadStoreStats() { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const requestedStoreUid = _this6.selectedStoreUid(); if (!requestedStoreUid) return; _this6.storeStats.set(undefined); try { const stats = yield _this6.storeList.getStoreStatistics(requestedStoreUid); if (requestedStoreUid === _this6.selectedStoreUid()) _this6.storeStats.set(stats); } catch { if (requestedStoreUid === _this6.selectedStoreUid()) _this6.storeStats.set({}); } })(); } /** Filter change: reset to page 1 and re-search over the (already-accumulated) set. */ setCriteria(criteria) { this.criteria.set(criteria); this.first.set(0); this.runSearch(); } /** Sort change from the table header. Resets to page 1. */ applySort(sort) { this.sortSpec.set(sort); this.first.set(0); this.runSearch(); } setPage(first, rows) { this.first.set(first); this.pageSize.set(rows); this.runSearch(); } /** Force a fresh accumulation from the store (drops the adapter cache). */ reloadStudies() { this.provider.invalidate(this.selectedStoreUid()); this.reviewStatuses.set(new Map()); this.runSearch(); } runSearch() { const storeUid = this.selectedStoreUid(); if (!storeUid) { this.page.set(EMPTY_PAGE); return; } this.query$.next({ criteria: this.criteria(), page: { limit: this.pageSize(), offset: this.first() }, reviewStatuses: this.reviewStatuses(), sort: this.sortSpec(), storeUid }); } static ɵfac = function PatientLibraryListFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PatientLibraryListFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: PatientLibraryListFacade, factory: PatientLibraryListFacade.ɵfac }); } /***/ }, /***/ 22357 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/patient-library.component.ts ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PatientLibraryComponent: () => (/* binding */ PatientLibraryComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _patient_library_details_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./patient-library-details.component */ 71086); /* harmony import */ var _patient_library_list_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./patient-library-list.component */ 33784); /* harmony import */ var _patient_library_list_facade__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./patient-library-list.facade */ 67045); /* harmony import */ var _series_sort_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./series-sort.store */ 14900); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); function PatientLibraryComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "lib-patient-library-details", 2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("back", function PatientLibraryComponent_Conditional_1_Template_lib_patient_library_details_back_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.closeStudy()); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } if (rf & 2) { const study_r3 = ctx; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("studyUid", study_r3.studyUid)("storeUid", study_r3.storeUid)("cacheAllOnOpen", study_r3.cacheAll)("numberOfInstancesHint", study_r3.numberOfInstances); } } function PatientLibraryComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "lib-patient-library-list", 3); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("studySelected", function PatientLibraryComponent_Conditional_2_Template_lib_patient_library_list_studySelected_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.openStudy($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } } class PatientLibraryComponent { facade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_3__.PatientLibraryListFacade); openedStudy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "openedStudy" }] : [])); constructor() { // Switching stores invalidates the opened study, so fall back to the study list. (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { this.facade.selectedStoreUid(); this.openedStudy.set(undefined); }); } openStudy(study) { this.openedStudy.set(study); } closeStudy() { this.openedStudy.set(undefined); } static ɵfac = function PatientLibraryComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PatientLibraryComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: PatientLibraryComponent, selectors: [["lib-patient-library"]], hostAttrs: [1, "block", "h-full"], features: [_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵProvidersFeature"]([_series_sort_store__WEBPACK_IMPORTED_MODULE_4__.SeriesSortStore])], decls: 3, vars: 1, consts: [[1, "h-full"], [3, "studyUid", "storeUid", "cacheAllOnOpen", "numberOfInstancesHint"], [3, "back", "studyUid", "storeUid", "cacheAllOnOpen", "numberOfInstancesHint"], [3, "studySelected"]], template: function PatientLibraryComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "div", 0); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](1, PatientLibraryComponent_Conditional_1_Template, 1, 4, "lib-patient-library-details", 1)(2, PatientLibraryComponent_Conditional_2_Template, 1, 0, "lib-patient-library-list"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"]((tmp_0_0 = ctx.openedStudy()) ? 1 : 2, tmp_0_0); } }, dependencies: [_patient_library_list_component__WEBPACK_IMPORTED_MODULE_2__.PatientLibraryListComponent, _patient_library_details_component__WEBPACK_IMPORTED_MODULE_1__.PatientLibraryDetailsComponent], encapsulation: 2 }); } /***/ }, /***/ 36088 /*!*********************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/series-bulk-actions.component.ts ***! \*********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SeriesBulkActionsComponent: () => (/* binding */ SeriesBulkActionsComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ count: a0 }); function SeriesBulkActionsComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 0)(1, "p-button", 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function SeriesBulkActionsComponent_Conditional_0_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵresetView"](ctx_r1.clear.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](4, "lib-icon", 2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](5, "span", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](8, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](10, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function SeriesBulkActionsComponent_Conditional_0_Template_p_button_click_10_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵresetView"](ctx_r1.view.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](12, "lib-icon", 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](13, "p-button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](14, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](15, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function SeriesBulkActionsComponent_Conditional_0_Template_p_button_click_13_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵresetView"](ctx_r1.cache.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](16, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](17, "p-button", 9); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](19, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function SeriesBulkActionsComponent_Conditional_0_Template_p_button_click_17_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵresetView"](ctx_r1.more.emit($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](20, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](2, 12, "patientDetails.bulkActions.clear"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](3, 14, "patientDetails.bulkActions.clear")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind2"](7, 16, "patientDetails.bulkActions.selected", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](31, _c0, ctx_r1.selectedCount())), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", ctx_r1.viewBlockedReason() || _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](9, 19, "patientDetails.bulkActions.view")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("severity", ctx_r1.viewBlockedReason() ? "secondary" : "primary")("disabled", !!ctx_r1.viewBlockedReason())("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](11, 21, "patientDetails.bulkActions.view")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("disabled", ctx_r1.cacheableCount() === 0)("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](14, 23, "patientDetails.bulkActions.cacheSelected"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](15, 25, "patientDetails.bulkActions.cacheSelected")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](18, 27, "patientDetails.bulkActions.more"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](19, 29, "patientDetails.bulkActions.more")); } } class SeriesBulkActionsComponent { selectedCount = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "selectedCount" }] : [])); cacheableCount = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "cacheableCount" }] : [])); /** Empty when the selection can be opened; otherwise why it cannot. */ viewBlockedReason = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "viewBlockedReason" }] : [])); view = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); cache = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); clear = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); more = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); static ɵfac = function SeriesBulkActionsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SeriesBulkActionsComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: SeriesBulkActionsComponent, selectors: [["lib-series-bulk-actions"]], inputs: { selectedCount: [1, "selectedCount"], cacheableCount: [1, "cacheableCount"], viewBlockedReason: [1, "viewBlockedReason"] }, outputs: { view: "view", cache: "cache", clear: "clear", more: "more" }, decls: 1, vars: 1, consts: [["data-test-id", "patient-library-div-bulk-actions", 1, "border-primary-500/30", "bg-primary-500/10", "flex", "items-center", "gap-1.5", "rounded-full", "border", "py-1", "pr-2", "pl-1.5"], ["data-test-id", "patient-library-p-button-clear-selection", "severity", "secondary", "text", "", "rounded", "", "size", "small", "tooltipPosition", "bottom", 3, "click", "pTooltip", "ariaLabel"], ["icon", "times", 1, "size-(--p-app-icon-size-xxs)"], [1, "text-primary-200", "text-sm", "whitespace-nowrap"], ["tooltipPosition", "bottom", 1, "inline-flex", 3, "pTooltip"], ["data-test-id", "patient-library-p-button-bulk-view", "text", "", "rounded", "", "size", "small", 3, "click", "severity", "disabled", "ariaLabel"], ["icon", "eye", 1, "size-(--p-app-icon-size-xs)"], ["data-test-id", "patient-library-p-button-bulk-cache", "severity", "secondary", "text", "", "rounded", "", "size", "small", "tooltipPosition", "bottom", 3, "click", "disabled", "pTooltip", "ariaLabel"], ["icon", "cloud-download", 1, "size-(--p-app-icon-size-xs)"], ["data-test-id", "patient-library-p-button-bulk-menu", "severity", "secondary", "text", "", "rounded", "", "size", "small", "tooltipPosition", "bottom", 3, "click", "pTooltip", "ariaLabel"], ["icon", "ellipsis-h", 1, "size-(--p-app-icon-size-xs)"]], template: function SeriesBulkActionsComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](0, SeriesBulkActionsComponent_Conditional_0_Template, 21, 33, "div", 0); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx.selectedCount() > 0 ? 0 : -1); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__.IconComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateModule, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 8487 /*!********************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/series-cache-tasks.component.ts ***! \********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SeriesCacheTasksComponent: () => (/* binding */ SeriesCacheTasksComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var _series_cache_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./series-cache.service */ 60240); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["taskPopover"]; const _c1 = ["taskButton"]; const _c2 = a0 => ({ count: a0 }); const _c3 = () => ({ height: "4px" }); const _forTrack0 = ($index, $item) => $item.id; function SeriesCacheTasksComponent_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](1, 1, "patientDetails.caching.taskCountOne"), " "); } } function SeriesCacheTasksComponent_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](1, "translate"); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind2"](1, 1, "patientDetails.caching.taskCountOther", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](4, _c2, ctx_r2.pendingCount())), " "); } } function SeriesCacheTasksComponent_Conditional_0_For_14_Conditional_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](1, 1, "patientDetails.caching.done"), " "); } } function SeriesCacheTasksComponent_Conditional_0_For_14_Conditional_8_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](0); } if (rf & 2) { const task_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", task_r4.progress, "% "); } } function SeriesCacheTasksComponent_Conditional_0_For_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "li", 8)(1, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](2, "i", 10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](3, "span", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](6, "span", 12); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](7, SeriesCacheTasksComponent_Conditional_0_For_14_Conditional_7_Template, 2, 3)(8, SeriesCacheTasksComponent_Conditional_0_For_14_Conditional_8_Template, 1, 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](9, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](11, "p-progressBar", 14); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const task_r4 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵclassMap"](task_r4.done ? "text-(--p-app-status-success)" : "text-primary-400"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](5, 9, "patientDetails.caching.cacheLocally"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](task_r4.done ? 7 : 8); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](task_r4.detail); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵstyleMap"](_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](11, _c3)); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("value", task_r4.progress)("showValue", false); } } function SeriesCacheTasksComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "button", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function SeriesCacheTasksComponent_Conditional_0_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const taskPopover_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵreference"](7); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](taskPopover_r2.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](2, "i", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](3, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](4, SeriesCacheTasksComponent_Conditional_0_Conditional_4_Template, 2, 3)(5, SeriesCacheTasksComponent_Conditional_0_Conditional_5_Template, 2, 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](6, "p-popover", null, 1)(8, "div", 5)(9, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](12, "ul", 7); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵrepeaterCreate"](13, SeriesCacheTasksComponent_Conditional_0_For_14_Template, 12, 12, "li", 8, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx_r2.pendingCount() === 1 ? 4 : 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](11, 2, "patientDetails.caching.title"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵrepeater"](ctx_r2.tasks()); } } class SeriesCacheTasksComponent { cache = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_series_cache_service__WEBPACK_IMPORTED_MODULE_5__.SeriesCacheService); tasks = this.cache.tasks; pendingCount = this.cache.pendingCount; popover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)('taskPopover', ...(ngDevMode ? [{ debugName: "popover" }] : [])); trigger = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)('taskButton', ...(ngDevMode ? [{ debugName: "trigger" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { if (this.cache.openRequested() === 0) return; // The anchor button only renders once a task exists. queueMicrotask(() => { const anchor = this.trigger()?.nativeElement; if (anchor) this.popover()?.show(undefined, anchor); }); }); } static ɵfac = function SeriesCacheTasksComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SeriesCacheTasksComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: SeriesCacheTasksComponent, selectors: [["lib-series-cache-tasks"]], viewQuery: function SeriesCacheTasksComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵviewQuerySignal"](ctx.popover, _c0, 5)(ctx.trigger, _c1, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](2); } }, decls: 1, vars: 1, consts: [["taskButton", ""], ["taskPopover", ""], ["type", "button", "data-test-id", "patient-library-button-cache-tasks", 1, "hover:bg-surface-800", "ml-3", "flex", "cursor-pointer", "items-center", "gap-2", "rounded-md", "px-2.5", "py-1.5", 3, "click"], [1, "pi", "pi-spin", "pi-spinner", "text-primary-400", "text-sm"], [1, "text-sm"], [1, "w-80"], [1, "border-surface-700", "mb-2", "border-b", "pb-2", "text-sm", "font-medium"], [1, "flex", "max-h-80", "flex-col", "gap-2.5", "overflow-y-auto"], [1, "border-surface-700", "bg-surface-900/60", "rounded-lg", "border", "p-2.5"], [1, "flex", "items-center", "gap-2"], [1, "pi", "pi-cloud-download", "shrink-0", "text-sm"], [1, "truncate", "text-sm"], [1, "text-muted-color", "ml-auto", "shrink-0", "text-xs", "tabular-nums"], [1, "text-muted-color", "mt-0.5", "truncate", "text-xs"], ["styleClass", "mt-2", 3, "value", "showValue"]], template: function SeriesCacheTasksComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](0, SeriesCacheTasksComponent_Conditional_0_Template, 15, 4); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx.pendingCount() > 0 ? 0 : -1); } }, dependencies: [primeng_popover__WEBPACK_IMPORTED_MODULE_3__.PopoverModule, primeng_popover__WEBPACK_IMPORTED_MODULE_3__.Popover, primeng_progressbar__WEBPACK_IMPORTED_MODULE_4__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_4__.ProgressBar, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateModule, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 60240 /*!************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/series-cache.service.ts ***! \************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SeriesCacheService: () => (/* binding */ SeriesCacheService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 8102); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 9276); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); const DONE_LINGER_MS = 1500; function seriesKey(target) { return `${target.storeUid}::${target.seriesUid}`; } class SeriesCacheService { database = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.DicomDatabaseService); _tasks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "_tasks" }] : [])); sequence = 0; pendingCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this._tasks().filter(task => !task.done).length, ...(ngDevMode ? [{ debugName: "pendingCount" }] : [])); /** A counter rather than a flag, so a second task re-opens an already-dismissed tracker. */ openRequested = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "openRequested" }] : [])); activeTargets = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this._tasks().filter(task => !task.done).flatMap(task => task.targets), ...(ngDevMode ? [{ debugName: "activeTargets" }] : [])); activeKeys = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => new Set(this.activeTargets().map(target => seriesKey(target))), ...(ngDevMode ? [{ debugName: "activeKeys" }] : [])); trackedByStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const byStore = new Map(); for (const task of this._tasks()) { for (const { seriesUid, storeUid } of task.targets) { const seriesUids = byStore.get(storeUid); if (seriesUids) seriesUids.push(seriesUid);else byStore.set(storeUid, [seriesUid]); } } return byStore; }, ...(ngDevMode ? [{ debugName: "trackedByStore" }] : [])); // Counts come from persisted attachments, so a partly-cached series resumes at its real // position rather than restarting from zero. progress = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toObservable)(this.trackedByStore).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_7__.distinctUntilChanged)((previous, next) => signature(previous) === signature(next)), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.switchMap)(byStore => byStore.size === 0 ? (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)({}) : (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.combineLatest)([...byStore].map(([storeUid, seriesUids]) => this.database.streamSeriesCacheProgressBySeries(seriesUids, storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_8__.map)(bySeries => Object.fromEntries(Object.entries(bySeries).map(([seriesUid, seriesProgress]) => [seriesKey({ seriesUid, storeUid }), seriesProgress]))), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.of)({})), // combineLatest stays silent until every store's first query resolves. (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.startWith)({})))).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_8__.map)(perStore => { const merged = {}; for (const chunk of perStore) Object.assign(merged, chunk); return merged; })))), { initialValue: {} }); tasks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const progress = this.progress(); return this._tasks().map(task => { let cachedCount = 0; let totalCount = 0; for (const target of task.targets) { const seriesProgress = progress[seriesKey(target)]; cachedCount += seriesProgress?.cachedCount ?? 0; totalCount += seriesProgress?.totalCount ?? 0; } const cached = totalCount ? Math.round(cachedCount / totalCount * 100) : 0; return { ...task, progress: task.done ? 100 : cached }; }); }, ...(ngDevMode ? [{ debugName: "tasks" }] : [])); requestOpen() { this.openRequested.update(count => count + 1); } // Keyed by store as well as series: the same series UID can sit in more than one store, and // caching it from one must not mark it busy in the other. isCachingSeries(target) { return this.activeKeys().has(seriesKey(target)); } /** Caches every target as one task; `detail` is the card's subtitle. */ cache(targets, detail) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const fresh = targets.filter(target => !_this.isCachingSeries(target)); if (fresh.length === 0) return; const id = `series-cache-${++_this.sequence}`; _this._tasks.update(tasks => [...tasks, { detail, done: false, id, targets: fresh }]); _this.requestOpen(); try { const results = yield Promise.allSettled(fresh.map(target => _this.database.ensureSeriesCached(target.studyUid, target.seriesUid, target.storeUid))); const failure = results.find(result => result.status === 'rejected'); if (failure) throw failure.reason; } finally { _this.settle(id); } })(); } settle(id) { this._tasks.update(tasks => tasks.map(task => task.id === id ? { ...task, done: true } : task)); setTimeout(() => this._tasks.update(tasks => tasks.filter(task => task.id !== id)), DONE_LINGER_MS); } static ɵfac = function SeriesCacheService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SeriesCacheService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: SeriesCacheService, factory: SeriesCacheService.ɵfac }); } function signature(byStore) { return [...byStore].map(([storeUid, seriesUids]) => `${storeUid}:${seriesUids}`).join('|'); } /***/ }, /***/ 54759 /*!***********************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/series-cacheability.ts ***! \***********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ hasWorkSessionInstance: () => (/* binding */ hasWorkSessionInstance), /* harmony export */ resolveSeriesValidationErrors: () => (/* binding */ resolveSeriesValidationErrors) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * CT-geometry rules a tvCT OT annotation series is exempt from: these fields are * intentionally absent from Secondary Capture OT files. */ const CT_ONLY_ERRORS = new Set(['ImageOrientationPatient is required field for all instances.', _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.MODALITY_CT_ERROR_MESSAGE, 'PixelSpacing is required field for all instances.', 'SliceThickness is required field for all instances.']); function hasWorkSessionInstance(documents) { return documents.some(document_ => { const meta = document_.toJSON().metadata; return meta !== undefined && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.isTvctWorkSessionInstance)(meta); }); } /** * Everything that stops a series being opened, and so cached. An OT series only qualifies * when its instances identify it as a tvCT analysis, plain OT is not viewable. */ function resolveSeriesValidationErrors(modality, documents) { const seriesMetadata = documents.map(document_ => document_.toJSON()); const errors = [...new Set([...(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.validateCtModality)(modality), ...(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.validateInstances)(seriesMetadata)])]; if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.normalizeModality)(modality) === 'OT' && hasWorkSessionInstance(documents)) { return errors.filter(error => !CT_ONLY_ERRORS.has(error)); } return errors; } /***/ }, /***/ 14900 /*!*********************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/patient-library/series-sort.store.ts ***! \*********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SeriesSortStore: () => (/* binding */ SeriesSortStore) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /** * Series-table sort order, kept separate from the study list's sort so switching * one never clobbers the other. Provided on PatientLibraryComponent so it outlives * PatientLibraryDetailsComponent, which is destroyed and recreated every time a * study is opened or closed. */ class SeriesSortStore { sortSpec = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "sortSpec" }] : [])); setSort(sort) { this.sortSpec.set(sort); } static ɵfac = function SeriesSortStore_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SeriesSortStore)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: SeriesSortStore, factory: SeriesSortStore.ɵfac }); } /***/ }, /***/ 80325 /*!*************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/review-dialog/review-dialog.component.ts ***! \*************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ReviewDialogComponent: () => (/* binding */ ReviewDialogComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_progressspinner__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/progressspinner */ 7271); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_textarea__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/textarea */ 25683); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../services/annotation-export-bridge.service */ 68674); /* harmony import */ var _services_dicom_export_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../services/dicom-export.service */ 8027); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/api */ 62751); function ReviewDialogComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](1, "p-progressSpinner", 6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](2, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](4, 1, "dicomImporter.reviewDialog.submitting"), " "); } } function ReviewDialogComponent_Conditional_2_ng_template_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](1, "translate"); } if (rf & 2) { const item_r3 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](1, 1, "dicomImporter.reviewDialog.reasons." + item_r3.value), " "); } } function ReviewDialogComponent_Conditional_2_ng_template_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](1, "translate"); } if (rf & 2) { const selectedOption_r4 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](1, 1, "dicomImporter.reviewDialog.reasons." + selectedOption_r4.value), " "); } } function ReviewDialogComponent_Conditional_2_Conditional_17_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p", 15); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](2, 1, ctx), " "); } } function ReviewDialogComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](3, "div", 8)(4, "label", 9); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](7, "p-select", 10); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("ngModelChange", function ReviewDialogComponent_Conditional_2_Template_p_select_ngModelChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.onReasonCodeChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](9, ReviewDialogComponent_Conditional_2_ng_template_9_Template, 2, 3, "ng-template", 11)(10, ReviewDialogComponent_Conditional_2_ng_template_10_Template, 2, 3, "ng-template", 12); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](11, "div", 8)(12, "label", 13); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](13); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](14, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](15, "textarea", 14); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](16, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("ngModelChange", function ReviewDialogComponent_Conditional_2_Template_textarea_ngModelChange_15_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.onCommentChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](17, ReviewDialogComponent_Conditional_2_Conditional_17_Template, 3, 3, "p", 15); } if (rf & 2) { let tmp_9_0; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](2, 9, "dicomImporter.reviewDialog.description"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](6, 11, "dicomImporter.reviewDialog.reasonLabel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("options", ctx_r1.reasonCodes)("ngModel", ctx_r1.reasonCode())("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](8, 13, "dicomImporter.reviewDialog.reasonPlaceholder")); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](14, 15, "dicomImporter.reviewDialog.commentLabel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("ngModel", ctx_r1.comment())("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](16, 17, "dicomImporter.reviewDialog.commentPlaceholder")); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"]((tmp_9_0 = ctx_r1.validationError()) ? 17 : -1, tmp_9_0); } } /** Approve/reject dialog for the open OT session; writes a new reviewed instance into the same series. */ class ReviewDialogComponent { ref = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__.DynamicDialogRef); exportService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_11__.DicomExportService); bridge = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_10__.AnnotationExportBridge); auth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.AuthService); state = this.exportService.state; comment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)('', ...(ngDevMode ? [{ debugName: "comment" }] : [])); reasonCode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "reasonCode" }] : [])); /** Set when a rejection is submitted incomplete; cleared as soon as the reviewer edits. */ validationError = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "validationError" }] : [])); reasonCodes = [{ value: 'R1' }, { value: 'R2' }, { value: 'R3' }, { value: 'R4' }, { value: 'R5' }, { value: 'R6' }, { value: 'R7' }, { value: 'R8' }, { value: 'R9' }]; onSubmit(status) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const context = _this.bridge.reviewContext(); const user = _this.auth.currentUser(); // Nothing to submit against - not recoverable from inside the dialog. if (!context || !user) { _this.ref.close(); return; } // Recoverable: hold the dialog open so the reviewer can complete it rather than // silently discarding what they had already entered. const rejectionError = _this.rejectionError(status); if (rejectionError) { _this.validationError.set(rejectionError); return; } _this.validationError.set(undefined); try { const protocolFormValues = _this.bridge.protocolFormValues(); yield _this.exportService.reviewSeriesToStore({ annotations: _this.bridge.annotations(), comment: _this.comment().trim(), context, protocolBindings: _this.bridge.protocolBindings(), ...(protocolFormValues ? { protocolFormValues } : {}), ...(status === 'REJECTED' ? { reasonCode: _this.reasonCode() } : {}), reviewerName: _this.bridge.author, reviewerUserId: _this.bridge.authorUserId, status }); _this.ref.close({ messageKey: 'dicomImporter.reviewDialog.toast.success', severity: 'success' }); } catch (error) { _this.ref.close({ detail: error.message, messageKey: 'dicomImporter.reviewDialog.toast.error', severity: 'error' }); } })(); } /** Clears the error the moment either input changes, so it never contradicts the form. */ onReasonCodeChange(reasonCode) { this.reasonCode.set(reasonCode); this.validationError.set(undefined); } onCommentChange(comment) { this.comment.set(comment); this.validationError.set(undefined); } rejectionError(status) { if (status !== 'REJECTED') return; if (!this.reasonCode()) return 'dicomImporter.reviewDialog.error.reasonRequired'; if (this.reasonCode() === 'R9' && !this.comment().trim()) { return 'dicomImporter.reviewDialog.error.commentRequiredForOther'; } return undefined; } onCancel() { this.ref.close(); } static ɵfac = function ReviewDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ReviewDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵdefineComponent"]({ type: ReviewDialogComponent, selectors: [["lib-review-dialog"]], features: [_angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵProvidersFeature"]([_services_dicom_export_service__WEBPACK_IMPORTED_MODULE_11__.DicomExportService])], decls: 13, vars: 13, consts: [[1, "flex", "flex-col", "gap-6", "p-4"], [1, "flex", "flex-col", "items-center", "gap-3", "py-4"], [1, "flex", "justify-end", "gap-2"], ["data-test-id", "review-dialog-p-button-cancel", "severity", "secondary", "outlined", "", 3, "click", "disabled"], ["data-test-id", "review-dialog-p-button-reject", "severity", "danger", "outlined", "", 3, "click", "disabled"], ["data-test-id", "review-dialog-p-button-approve", 3, "click", "disabled"], ["strokeWidth", "4", 1, "size-12"], [1, "text-muted-color", "text-sm"], [1, "flex", "flex-col", "gap-2"], ["for", "review-reason", 1, "text-sm", "font-medium"], ["inputId", "review-reason", "data-test-id", "review-dialog-p-select-reason", "optionValue", "value", 3, "ngModelChange", "options", "ngModel", "placeholder"], ["pTemplate", "item"], ["pTemplate", "selectedItem"], ["for", "review-comment", 1, "text-sm", "font-medium"], ["id", "review-comment", "data-test-id", "review-dialog-textarea-comment", "pTextarea", "", "fluid", "", "rows", "3", 3, "ngModelChange", "ngModel", "placeholder"], ["data-test-id", "review-dialog-p-validation-error", "role", "alert", 1, "text-sm", "text-(--p-app-status-danger)"]], template: function ReviewDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 0); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](1, ReviewDialogComponent_Conditional_1_Template, 5, 3, "div", 1)(2, ReviewDialogComponent_Conditional_2_Template, 18, 19); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](3, "div", 2)(4, "p-button", 3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function ReviewDialogComponent_Template_p_button_click_4_listener() { return ctx.onCancel(); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](7, "p-button", 4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function ReviewDialogComponent_Template_p_button_click_7_listener() { return ctx.onSubmit("REJECTED"); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](10, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function ReviewDialogComponent_Template_p_button_click_10_listener() { return ctx.onSubmit("APPROVED"); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.state() === "exporting" ? 1 : 2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("disabled", ctx.state() === "exporting"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](6, 7, "common.cancel"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("disabled", ctx.state() === "exporting"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](9, 9, "dicomImporter.reviewDialog.reject"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("disabled", ctx.state() === "exporting"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](12, 11, "dicomImporter.reviewDialog.approve"), " "); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_4__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_4__.Button, primeng_api__WEBPACK_IMPORTED_MODULE_13__.PrimeTemplate, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgModel, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_6__.ProgressSpinnerModule, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_6__.ProgressSpinner, primeng_select__WEBPACK_IMPORTED_MODULE_7__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_7__.Select, primeng_textarea__WEBPACK_IMPORTED_MODULE_8__.TextareaModule, primeng_textarea__WEBPACK_IMPORTED_MODULE_8__.Textarea, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateModule, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 92729 /*!***********************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/review-status-icon/review-status-icon.component.ts ***! \***********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ReviewStatusIconComponent: () => (/* binding */ ReviewStatusIconComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); function ReviewStatusIconComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "span", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](3, "lib-icon", 2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } if (rf & 2) { const d_r1 = ctx; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"](d_r1.colorClass); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipeBind1"](1, 5, d_r1.labelKey)); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpipeBind1"](2, 7, d_r1.labelKey)); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("icon", d_r1.icon); } } /** Shared tri-state review indicator (study library, Study Series table, instance picker). */ class ReviewStatusIconComponent { status = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "status" }] : [])); display = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { switch (this.status()) { case 'approved': { return { colorClass: 'text-(--p-app-review-approved)', icon: 'check', labelKey: 'reviewStatus.approved' }; } case 'rejected': { return { colorClass: 'text-(--p-app-review-rejected)', icon: 'times', labelKey: 'reviewStatus.rejected' }; } case 'unapproved': { return { colorClass: 'text-(--p-app-review-pending)', icon: 'clock', labelKey: 'reviewStatus.unapproved' }; } default: { return; } } }, ...(ngDevMode ? [{ debugName: "display" }] : [])); static ɵfac = function ReviewStatusIconComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ReviewStatusIconComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: ReviewStatusIconComponent, selectors: [["lib-review-status-icon"]], inputs: { status: [1, "status"] }, decls: 1, vars: 1, consts: [["role", "img", "tooltipPosition", "top", 3, "class", "pTooltip"], ["role", "img", "tooltipPosition", "top", 3, "pTooltip"], [3, "icon"]], template: function ReviewStatusIconComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](0, ReviewStatusIconComponent_Conditional_0_Template, 4, 9, "span", 0); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"]((tmp_0_0 = ctx.display()) ? 0 : -1, tmp_0_0); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__.IconComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 88507 /*!***************************************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/components/work-session-library/work-session-library.component.ts ***! \***************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionLibraryComponent: () => (/* binding */ WorkSessionLibraryComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 84356); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 8102); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs */ 9276); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs */ 45541); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ "min-width": "70rem", "table-layout": "fixed" }); function WorkSessionLibraryComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", ctx_r1.error(), " "); } } function WorkSessionLibraryComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "tr")(1, "th", 15); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](4, "th", 15); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](7, "th", 15); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](10, "th", 16); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](13, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](14); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](15, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](16, "th", 17); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](19, "th", 18); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](20, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](21, "lib-icon", 19); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](22, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](23, "th", 20); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](25, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](3, 9, "dicomImporter.workSessions.table.session")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](6, 11, "dicomImporter.workSessions.table.patientName"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](9, 13, "dicomImporter.workSessions.table.store")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](12, 15, "dicomImporter.workSessions.table.modality")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](15, 17, "dicomImporter.workSessions.table.description"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](18, 19, "dicomImporter.workSessions.table.updatedAt"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](20, 21, "dicomImporter.workSessions.table.localCache")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](22, 23, "dicomImporter.workSessions.table.localCache")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](25, 25, "dicomImporter.workSessions.table.actions"), " "); } } function WorkSessionLibraryComponent_ng_template_4_Conditional_23_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "span", 24); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](2, "lib-icon", 32); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](1, 2, "dicomImporter.workSessions.cachedLocally")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](3, 4, "dicomImporter.workSessions.cachedLocally")); } } function WorkSessionLibraryComponent_ng_template_4_Conditional_24_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "div", 25); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](1, "p-progressBar", 33); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const cache_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](22); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("showValue", false)("value", cache_r6.percent); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate2"]("", cache_r6.cachedCount, "/", cache_r6.totalCount); } } function WorkSessionLibraryComponent_ng_template_4_Conditional_25_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "div", 26)(1, "span", 34); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](3, "p-button", 35); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵlistener"]("click", function WorkSessionLibraryComponent_ng_template_4_Conditional_25_Template_p_button_click_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const row_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.cacheRow(row_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](5, "lib-icon", 36); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const row_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](2, 3, "dicomImporter.workSessions.cacheLocally")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](4, 5, "dicomImporter.workSessions.cacheLocally"))("disabled", ctx_r1.loading() || ctx_r1.isCaching(row_r4)); } } function WorkSessionLibraryComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵdeclareLet"](0); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](1, "tr", 21); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵlistener"]("contextmenu", function WorkSessionLibraryComponent_ng_template_4_Template_tr_contextmenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const row_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const rowMenuContext_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](9); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.rowMenu.openAtPointer(rowMenuContext_r5, $event, row_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](2, "td", 22, 2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](5, "td", 22, 3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](8, "td", 22, 4); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](11, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](12); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](13, "td", 22, 5); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](15); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](16, "td", 22, 6); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](18, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](19); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](20, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](21, "td", 23); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵdeclareLet"](22); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵconditionalCreate"](23, WorkSessionLibraryComponent_ng_template_4_Conditional_23_Template, 4, 6, "span", 24)(24, WorkSessionLibraryComponent_ng_template_4_Conditional_24_Template, 4, 4, "div", 25)(25, WorkSessionLibraryComponent_ng_template_4_Conditional_25_Template, 6, 7, "div", 26); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](26, "td")(27, "div", 27)(28, "p-button", 28); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](29, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵlistener"]("click", function WorkSessionLibraryComponent_ng_template_4_Template_p_button_click_28_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const row_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.open(row_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](30, "lib-icon", 29); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](31, "p-button", 30); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](32, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵlistener"]("click", function WorkSessionLibraryComponent_ng_template_4_Template_p_button_click_31_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const row_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreadContextLet"](0); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const rowMenuPopup_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](7); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.rowMenu.openFromButton(rowMenuPopup_r8, $event, row_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](33, "lib-icon", 31); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const rawRow_r9 = ctx.$implicit; const nameTip_r10 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](3); const patientNameTip_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](6); const storeTip_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](9); const descriptionTip_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](14); const updatedAtTip_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵreference"](17); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵnextContext"](); const row_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵstoreLet"](ctx_r1.asRow(rawRow_r9)); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pSelectableRow", row_r15); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", nameTip_r10.truncated() ? row_r15.name : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", row_r15.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", patientNameTip_r11.truncated() ? row_r15.patientName : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", row_r15.patientName, " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", storeTip_r12.truncated() ? row_r15.storeName : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", row_r15.storeName, " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate"](row_r15.modality); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", descriptionTip_r13.truncated() ? row_r15.seriesDescription : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", row_r15.seriesDescription, " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("pTooltip", updatedAtTip_r14.truncated() ? _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind2"](18, 17, row_r15.updatedAt, true) ?? row_r15.updatedAt : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind2"](20, 20, row_r15.updatedAt, true) ?? row_r15.updatedAt, " "); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); const cache_r16 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵstoreLet"](ctx_r1.progressFor(row_r15)); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵconditional"](ctx_r1.isFullyCached(row_r15) ? 23 : ctx_r1.isCaching(row_r15) || cache_r16.cachedCount > 0 ? 24 : 25); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("disabled", ctx_r1.loading() || ctx_r1.isActive(row_r15))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](29, 24, "dicomImporter.workSessions.menu.view")); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](32, 26, "dicomImporter.workSessions.table.actions")); } } function WorkSessionLibraryComponent_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "tr")(1, "td", 37); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpipeBind1"](3, 1, "dicomImporter.workSessions.empty")); } } const NO_CACHE_PROGRESS = { cachedCount: 0, percent: 0, totalCount: 0 }; class WorkSessionLibraryComponent { workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_23__.WorkSessionDatabaseService); dicomDatabase = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_23__.DicomDatabaseService); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_23__.DicomStoreListService); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_4__.Router); confirmationService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_15__.ConfirmationService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__.TranslateService); dialogRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_18__.DynamicDialogRef, { optional: true }); loading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(true, ...(ngDevMode ? [{ debugName: "loading" }] : [])); error = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "error" }] : [])); rows = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)(this.workSessionDb.workSessions$({}).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_13__.tap)(() => { this.loading.set(true); this.error.set(undefined); }), (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.switchMap)(sessions => (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.from)(this.buildRows(sessions)).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_13__.tap)(() => this.loading.set(false)), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.catchError)(error => { this.error.set(error.message ?? String(error)); this.loading.set(false); return (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.of)([]); })))), { initialValue: [] }); activeWorkSessionUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "activeWorkSessionUid" }] : [])); rowMenu = new _tomoverse_ui__WEBPACK_IMPORTED_MODULE_24__.RowMenuController(row => this.buildRowMenuItems(row)); cachingSeries = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)({}, ...(ngDevMode ? [{ debugName: "cachingSeries" }] : [])); seriesKey(row) { return `${row.storeUid}::${row.seriesUid}`; } isCaching(row) { return !!this.cachingSeries()[this.seriesKey(row)]; } groupSeriesByStore(rows) { const byStore = new Map(); for (const row of rows) { const seriesUids = byStore.get(row.storeUid) ?? new Set(); seriesUids.add(row.seriesUid); byStore.set(row.storeUid, seriesUids); } return new Map([...byStore].toSorted(([a], [b]) => a.localeCompare(b)).map(([storeUid, seriesUids]) => [storeUid, [...seriesUids].toSorted()])); } cacheProgress = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toObservable)(this.rows).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(rows => this.groupSeriesByStore(rows)), (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.distinctUntilChanged)((previous, next) => this.seriesSetSignature(previous) === this.seriesSetSignature(next)), (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.switchMap)(byStore => byStore.size === 0 ? (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.of)({}) : (0,rxjs__WEBPACK_IMPORTED_MODULE_5__.combineLatest)([...byStore].map(([storeUid, seriesUids]) => this.dicomDatabase.streamSeriesCacheProgressBySeries(seriesUids, storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(bySeries => Object.fromEntries(Object.entries(bySeries).map(([seriesUid, progress]) => [this.seriesKey({ seriesUid, storeUid }), progress]))), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.of)({})), (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.startWith)({})))).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(perStore => { const merged = {}; for (const chunk of perStore) Object.assign(merged, chunk); return merged; })))), { initialValue: {} }); seriesSetSignature(byStore) { return [...byStore].map(([storeUid, seriesUids]) => `${storeUid}:${seriesUids}`).join('|'); } progressFor(row) { return this.cacheProgress()[this.seriesKey(row)] ?? NO_CACHE_PROGRESS; } isFullyCached(row) { return (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_23__.isSeriesFullyCached)(this.progressFor(row)); } rowClickedRow = undefined; lastClickedRowUid = undefined; lastClickAtMs = 0; doubleClickThresholdMs = 300; open(row) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this.isActive(row)) return; _this.dialogRef?.close(); yield _this.router.navigate(['/volume-viewer', row.storeUid, row.studyUid, row.seriesUid, row.uid]); })(); } onRowSelect(event) { const row = Array.isArray(event?.data) ? event.data[0] : event?.data; const uid = row?.uid; const now = Date.now(); const isDoubleClick = uid !== undefined && uid === this.lastClickedRowUid && now - this.lastClickAtMs <= this.doubleClickThresholdMs; if (isDoubleClick) { this.lastClickedRowUid = undefined; this.lastClickAtMs = 0; if (row && !this.loading() && !this.isActive(row)) { this.open(row); } return; } this.lastClickedRowUid = uid; this.lastClickAtMs = now; } deleteRow(row) { var _this2 = this; if (this.isActive(row)) return; this.confirmationService.confirm({ accept: function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { yield _this2.workSessionDb.delete(row.uid); } catch (error) { _this2.error.set(error.message ?? String(error)); } }); return function accept() { return _ref.apply(this, arguments); }; }(), acceptButtonProps: { label: this.translate.instant('dicomImporter.workSessions.deleteSession.acceptLabel'), severity: 'danger' }, header: this.translate.instant('dicomImporter.workSessions.deleteSession.header'), icon: 'exclamation-triangle', message: this.translate.instant('dicomImporter.workSessions.deleteSession.message'), rejectButtonProps: { label: this.translate.instant('dicomImporter.workSessions.deleteSession.rejectLabel'), severity: 'secondary', text: true } }); } cacheRow(row) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const key = _this3.seriesKey(row); if (_this3.cachingSeries()[key]) return; _this3.cachingSeries.update(state => ({ ...state, [key]: true })); try { yield _this3.dicomDatabase.ensureSeriesCached(row.studyUid, row.seriesUid, row.storeUid); } catch (error) { _this3.error.set(error.message ?? String(error)); } finally { _this3.cachingSeries.update(({ [key]: _finished, ...rest }) => rest); } })(); } buildRowMenuItems(row) { return [{ command: () => this.open(row), disabled: this.loading() || this.isActive(row), icon: 'pi pi-box', label: this.translate.instant('dicomImporter.workSessions.menu.view') }, { separator: true }, { command: () => this.cacheRow(row), disabled: this.isCaching(row) || this.isFullyCached(row), icon: 'pi pi-cloud-download', label: this.translate.instant('dicomImporter.workSessions.menu.cache') }, { separator: true }, (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_24__.dangerMenuItem)({ command: () => this.deleteRow(row), disabled: this.loading() || this.isActive(row), icon: 'pi pi-trash', label: this.translate.instant('dicomImporter.workSessions.delete') })]; } asRow(value) { return value; } isActive(row) { return row.uid === this.activeWorkSessionUid(); } buildRows(sessions) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const metadataCache = new Map(); const sorted = sessions.toSorted((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()); const storeNamesByUid = yield _this4.resolveStoreNames(); const rows = yield Promise.all(sorted.map(/*#__PURE__*/function () { var _ref2 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (session) { const key = `${session.studyUid}::${session.seriesUid}`; if (!metadataCache.has(key)) { try { const metadata = yield _this4.dicomDatabase.getSeriesCommonMetadata(session.studyUid, session.seriesUid, session.storeUid); metadataCache.set(key, metadata); } catch { metadataCache.set(key, undefined); } } const metadata = metadataCache.get(key); return { modality: metadata?.modality ?? 'Unknown', name: session.name, patientName: metadata?.patientName ?? 'Unknown', seriesDescription: metadata?.seriesDescription ?? metadata?.studyDescription ?? 'Unknown', seriesUid: session.seriesUid, storeName: storeNamesByUid.get(session.storeUid) ?? session.storeUid, storeUid: session.storeUid, studyUid: session.studyUid, uid: session.uid, updatedAt: session.updatedAt }; }); return function (_x) { return _ref2.apply(this, arguments); }; }())); return [...rows]; })(); } resolveStoreNames() { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const stores = yield _this5.storeList.getEnabledStores(); return new Map(stores.map(store => [store.uid, store.name])); } catch { return new Map(); } })(); } static ɵfac = function WorkSessionLibraryComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionLibraryComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵdefineComponent"]({ type: WorkSessionLibraryComponent, selectors: [["lib-work-session-library"]], inputs: { activeWorkSessionUid: [1, "activeWorkSessionUid"] }, decls: 10, vars: 9, consts: [["rowMenuPopup", ""], ["rowMenuContext", ""], ["nameTip", "libEllipsisTip"], ["patientNameTip", "libEllipsisTip"], ["storeTip", "libEllipsisTip"], ["descriptionTip", "libEllipsisTip"], ["updatedAtTip", "libEllipsisTip"], [1, "flex", "h-full", "min-h-0", "flex-col", "py-4"], [1, "border-destructive/30", "bg-destructive/10", "text-destructive", "mx-4", "mb-4", "shrink-0", "rounded-md", "border", "px-3", "py-2"], ["dataKey", "uid", "selectionMode", "single", "scrollable", "", "scrollHeight", "flex", 1, "library-table", "min-h-0", "flex-1", 3, "selectionChange", "onRowSelect", "value", "loading", "tableStyle", "selection", "metaKeySelection"], ["pTemplate", "header"], ["pTemplate", "body"], ["pTemplate", "emptymessage"], ["data-test-id", "work-session-library-p-menu-row", "popup", "", "appendTo", "body", 3, "model"], ["data-test-id", "work-session-library-p-contextmenu-row", "appendTo", "body", 3, "model"], [1, "w-[10rem]"], [1, "w-[6.875rem]"], [1, "w-[11.5625rem]"], ["tooltipPosition", "top", 1, "w-[3.125rem]", "text-center", "whitespace-nowrap", 3, "pTooltip"], ["icon", "cloud-download", 1, "text-muted-color"], [1, "w-[8.4375rem]", "text-center"], [3, "contextmenu", "pSelectableRow"], ["libEllipsisTip", "", "tooltipPosition", "top", 3, "pTooltip"], [1, "text-center"], ["tooltipPosition", "top", 1, "text-muted-color", "inline-flex", "cursor-default", 3, "pTooltip"], [1, "text-muted-color", "flex", "items-center", "justify-center", "text-xs"], [1, "flex", "items-center", "justify-center", "gap-2"], [1, "flex", "items-center", "justify-end", "gap-2"], ["data-test-id", "work-session-library-p-button-open", "size", "small", "rounded", "", "text", "", "styleClass", "h-[30px] w-[30px] p-0", 3, "click", "disabled", "ariaLabel"], ["icon", "eye", 1, "size-(--p-app-icon-size-xs)"], ["data-test-id", "work-session-library-p-button-row-menu", "severity", "secondary", "size", "small", "text", "", 3, "click", "ariaLabel"], ["icon", "ellipsis-v"], ["icon", "check-circle"], [1, "mr-2", "h-2", "w-16", 3, "showValue", "value"], ["tooltipPosition", "top", 1, "inline-flex", 3, "pTooltip"], ["data-test-id", "work-session-library-p-button-cache", "severity", "secondary", "rounded", "", "text", "", "size", "small", "styleClass", "h-[30px] w-[30px] p-0", 3, "click", "ariaLabel", "disabled"], ["icon", "cloud-download", 1, "size-(--p-app-icon-size-xs)"], ["colspan", "8"]], template: function WorkSessionLibraryComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](0, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵconditionalCreate"](1, WorkSessionLibraryComponent_Conditional_1_Template, 2, 1, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementStart"](2, "p-table", 9); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtwoWayListener"]("selectionChange", function WorkSessionLibraryComponent_Template_p_table_selectionChange_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtwoWayBindingSet"](ctx.rowClickedRow, $event) || (ctx.rowClickedRow = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵlistener"]("onRowSelect", function WorkSessionLibraryComponent_Template_p_table_onRowSelect_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onRowSelect($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtemplate"](3, WorkSessionLibraryComponent_ng_template_3_Template, 26, 27, "ng-template", 10)(4, WorkSessionLibraryComponent_ng_template_4_Template, 34, 28, "ng-template", 11)(5, WorkSessionLibraryComponent_ng_template_5_Template, 4, 3, "ng-template", 12); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵelement"](6, "p-menu", 13, 0)(8, "p-contextmenu", 14, 1); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵconditional"](ctx.error() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("value", ctx.rows())("loading", ctx.loading())("tableStyle", _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵpureFunction0"](8, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵtwoWayProperty"]("selection", ctx.rowClickedRow); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("metaKeySelection", true); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("model", ctx.rowMenu.items()); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_26__["ɵɵproperty"]("model", ctx.rowMenu.items()); } }, dependencies: [primeng_table__WEBPACK_IMPORTED_MODULE_21__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_21__.Table, primeng_api__WEBPACK_IMPORTED_MODULE_15__.PrimeTemplate, primeng_table__WEBPACK_IMPORTED_MODULE_21__.SelectableRow, primeng_button__WEBPACK_IMPORTED_MODULE_16__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_16__.Button, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_17__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_17__.ContextMenu, primeng_menu__WEBPACK_IMPORTED_MODULE_19__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_19__.Menu, primeng_progressbar__WEBPACK_IMPORTED_MODULE_20__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_20__.ProgressBar, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__.TranslateModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_22__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_22__.Tooltip, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_24__.EllipsisTipDirective, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_24__.IconComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__.TranslatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_25__.DicomDatePipe], encapsulation: 2 }); } /***/ }, /***/ 68674 /*!******************************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/services/annotation-export-bridge.service.ts ***! \******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationExportBridge: () => (/* binding */ AnnotationExportBridge), /* harmony export */ buildProtocolBindings: () => (/* reexport safe */ _protocol_binding_utils__WEBPACK_IMPORTED_MODULE_3__.buildProtocolBindings), /* harmony export */ rebuildProtocolState: () => (/* reexport safe */ _protocol_binding_utils__WEBPACK_IMPORTED_MODULE_3__.rebuildProtocolState) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _protocol_binding_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./protocol-binding-utils */ 59639); /** Root bridge: the volume viewer shares annotation/protocol snapshots here for the export/review dialogs. */ class AnnotationExportBridge { auth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.AuthService); annotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "annotations" }] : [])); protocolBindings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "protocolBindings" }] : [])); protocolFormValues = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "protocolFormValues" }] : [])); reviewComment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('', ...(ngDevMode ? [{ debugName: "reviewComment" }] : [])); workSessionName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('', ...(ngDevMode ? [{ debugName: "workSessionName" }] : [])); sourceInstanceUIDs = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "sourceInstanceUIDs" }] : [])); activePhaseLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('', ...(ngDevMode ? [{ debugName: "activePhaseLabel" }] : [])); renderSettings2D = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "renderSettings2D" }] : [])); renderSettings3D = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "renderSettings3D" }] : [])); capturePreview = undefined; /** Set when the session was opened from an existing OT; undefined for fresh sessions. */ reviewContext = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "reviewContext" }] : [])); dirtySinceOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "dirtySinceOpen" }] : [])); /** Current user's stable id (accountId). */ get authorUserId() { return this.auth.currentUser()?.accountId ?? ''; } get author() { const user = this.auth.currentUser(); if (!user) return ''; return [user.name, user.lastName].filter(Boolean).join(' ').trim() || user.email; } /** Reviewable OT open, reviewer ≠ annotator, and annotations unchanged since open. */ canReview = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const context = this.reviewContext(); if (!context) return false; if (this.dirtySinceOpen()) return false; return this.authorUserId !== context.creatorUserId; }, ...(ngDevMode ? [{ debugName: "canReview" }] : [])); static ɵfac = function AnnotationExportBridge_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationExportBridge)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AnnotationExportBridge, factory: AnnotationExportBridge.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 19462 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/services/dicom-annotation-codec.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildScOtDicom: () => (/* binding */ buildScOtDicom), /* harmony export */ deserializeAnnotationPayload: () => (/* binding */ deserializeAnnotationPayload), /* harmony export */ extractAnnotationTags: () => (/* binding */ extractAnnotationTags), /* harmony export */ readDicomModality: () => (/* binding */ readDicomModality), /* harmony export */ readDicomStringTag: () => (/* binding */ readDicomStringTag), /* harmony export */ serializeAnnotationPayload: () => (/* binding */ serializeAnnotationPayload) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dicom_parser__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); // --------------------------------------------------------------------------- // Compression helpers (Web Streams API — available in all modern browsers) // --------------------------------------------------------------------------- function gzipBytes(_x) { return _gzipBytes.apply(this, arguments); } function _gzipBytes() { _gzipBytes = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (input) { const cs = new CompressionStream('gzip'); const writer = cs.writable.getWriter(); writer.write(input); writer.close(); return collectStream(cs.readable); }); return _gzipBytes.apply(this, arguments); } function gunzipBytes(_x2) { return _gunzipBytes.apply(this, arguments); } function _gunzipBytes() { _gunzipBytes = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (input) { const ds = new DecompressionStream('gzip'); const writer = ds.writable.getWriter(); // Suppress writable-side rejections — the error surfaces on the readable side via collectStream. writer.write(input).catch(() => { /* surfaces on readable side */ }); writer.close().catch(() => { /* surfaces on readable side */ }); return collectStream(ds.readable); }); return _gunzipBytes.apply(this, arguments); } function collectStream(_x3) { return _collectStream.apply(this, arguments); } // --------------------------------------------------------------------------- // Serialize / deserialize // --------------------------------------------------------------------------- /** Serialize the annotation payload to gzip-compressed JSON bytes. */ function _collectStream() { _collectStream = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (stream) { const chunks = []; const reader = stream.getReader(); for (;;) { const { done, value } = yield reader.read(); if (done) break; if (value) chunks.push(value); } const total = chunks.reduce((sum, c) => sum + c.length, 0); const out = new Uint8Array(total); let offset = 0; for (const chunk of chunks) { out.set(chunk, offset); offset += chunk.length; } return out; }); return _collectStream.apply(this, arguments); } function serializeAnnotationPayload(_x4) { return _serializeAnnotationPayload.apply(this, arguments); } /** Deserialize gzip-compressed JSON bytes back to an annotation payload. */ function _serializeAnnotationPayload() { _serializeAnnotationPayload = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (payload) { const json = new TextEncoder().encode(JSON.stringify(payload)); return gzipBytes(json); }); return _serializeAnnotationPayload.apply(this, arguments); } function deserializeAnnotationPayload(_x5) { return _deserializeAnnotationPayload.apply(this, arguments); } /** Tag key in dcmjs' 8-hex-digit uppercase form, e.g. (0008,0060) → "00080060". */ function _deserializeAnnotationPayload() { _deserializeAnnotationPayload = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (bytes) { let raw; try { raw = yield gunzipBytes(bytes); } catch { // Retry without the DICOM OB even-alignment null padding byte appended on write. raw = yield gunzipBytes(bytes.slice(0, -1)); } return _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__.annotationPayloadSchema.parse(JSON.parse(new TextDecoder().decode(raw))); }); return _deserializeAnnotationPayload.apply(this, arguments); } function tagKey(group, element) { return (group * 0x1_00_00 + element).toString(16).padStart(8, '0').toUpperCase(); } /** Build one denaturalized element. Empty strings stay as `['']` so Type-2 tags are written zero-length. */ function makeElement(vr, ...values) { return { Value: values, vr }; } /** OB element whose value is an exact-length copy of the bytes (dcmjs pads to even length on write). */ function makeObElement(data) { return { Value: [data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)], vr: 'OB' }; } // --------------------------------------------------------------------------- // Timezone offset helper // --------------------------------------------------------------------------- function formatTimezoneOffset() { const offsetMinutes = new Date().getTimezoneOffset(); const sign = offsetMinutes <= 0 ? '+' : '-'; const abs = Math.abs(offsetMinutes); const hh = Math.floor(abs / 60).toString().padStart(2, '0'); const mm = (abs % 60).toString().padStart(2, '0'); return `${sign}${hh}${mm}`; } // --------------------------------------------------------------------------- // SHA-256 helper // --------------------------------------------------------------------------- function sha256Hex(_x6) { return _sha256Hex.apply(this, arguments); } function _sha256Hex() { _sha256Hex = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (data) { const hashBuffer = yield crypto.subtle.digest('SHA-256', data); return [...new Uint8Array(hashBuffer)].map(b => b.toString(16).padStart(2, '0')).join(''); }); return _sha256Hex.apply(this, arguments); } function resolvePatientTagFallbacks(options) { return { accessionNumber: options.accessionNumber ?? '', patientBirthDate: options.patientBirthDate ?? '', patientID: options.patientID ?? '', patientName: options.patientName ?? '', patientSex: options.patientSex ?? '', studyDate: options.studyDate ?? '', studyDescription: options.studyDescription ?? '', studyID: options.studyID ?? '', studyTime: options.studyTime ?? '' }; } function resolveSeriesTagFallbacks(options, date, time) { return { seriesDate: options.seriesDate ?? date, seriesNumber: options.seriesNumber ?? 1, seriesTime: options.seriesTime ?? time }; } const SC_SOP_CLASS = '1.2.840.10008.5.1.4.1.1.7'; const EXPLICIT_VR_LE = '1.2.840.10008.1.2.1'; const IMPL_CLASS_UID = '1.3.6.1.4.1.66095.1.1.1'; const IMPL_VERSION = 'TVCT_DCM_1_0'; const PRIVATE_CREATOR = 'TOMOVERSE_TVCT_1'; const CT_SOP_CLASS = '1.2.840.10008.5.1.4.1.1.2'; const PRIVATE_TAG_PHASE_LABEL = 0x10_19; const PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION = 0x10_1a; const PRIVATE_TAG_SOURCE_INSTANCE_UIDS = 0x10_1b; const PRIVATE_TAG_SOURCE_SERIES_UID = 0x10_1c; const LEGACY_PRIVATE_TAG_SOURCE_INSTANCE_UIDS = 0x10_1a; const LEGACY_PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION = 0x10_1b; /** * Build a complete DICOM Part 10 file (Secondary Capture, OT modality) from scratch. * Contains a 1×1 black RGB placeholder pixel and the TVCT annotation payload in a * chunked private SQ at group 0029 (creator TOMOVERSE_TVCT_1). */ function buildScOtDicom(_x7) { return _buildScOtDicom.apply(this, arguments); } // --------------------------------------------------------------------------- // DICOM read helpers (dicom-parser) // // The exported OT file carries a standard Part-10 file-meta group, so we read it // back with dicom-parser's public `parseDicom`, which transparently handles the // undefined-length sequences dcmjs emits. Callers may pass arbitrary buffers, so // unparseable input resolves to `undefined` rather than throwing. // --------------------------------------------------------------------------- /** Tag lookup key in dicom-parser's `xggggeeee` form, e.g. (0008,0060) → "x00080060". */ function _buildScOtDicom() { _buildScOtDicom = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (options) { const { author = '', authorUserId = '', instanceCreationDate, instanceCreationTime, payload, payloadSchemaVersion, phaseLabel = '', reviewComment = '', reviewDate = '', reviewDateTime = '', reviewerName = '', reviewerUserId = '', reviewReasonCode = '', reviewStatus = 'UNAPPROVED', reviewTime = '', seriesDescription, seriesInstanceUID, softwareVersion, sopInstanceUID, sourceInstanceUIDs, sourceSeriesDescription = '', sourceSeriesUID, studyInstanceUID, workSessionRevision, workSessionUID } = options; // ── 1. Serialize + compress payload ─────────────────────────────────────── const fullPayload = { ...payload, sourceInstanceUIDs, sourceSeriesUID }; const jsonBytes = new TextEncoder().encode(JSON.stringify(fullPayload)); const originalLength = jsonBytes.length; const compressedBytes = yield gzipBytes(jsonBytes); // Pad to even length so (0029,1023) == OB element length (DICOM OB padding rule). // gzip ignores trailing bytes beyond the end-of-stream marker on decompression. const storedBytes = compressedBytes.length % 2 === 0 ? compressedBytes : new Uint8Array([...compressedBytes, 0x00]); const sha256 = yield sha256Hex(storedBytes); // ── 2. Build the chunked private payload sequence (0029,1009) ───────────── // Single chunk today; the reader reassembles by chunk index so multi-chunk // payloads remain forward-compatible. const payloadSq = makeElement('SQ', { [tagKey(0x00_29, 0x00_10)]: makeElement('LO', PRIVATE_CREATOR), [tagKey(0x00_29, 0x10_21)]: makeElement('UL', 0), [tagKey(0x00_29, 0x10_22)]: makeElement('UL', 1), [tagKey(0x00_29, 0x10_23)]: makeElement('UL', storedBytes.length), [tagKey(0x00_29, 0x10_24)]: makeObElement(storedBytes) }); // ── 3. Public reference sequences ──────────────────────────────────────── // (0008,1115) Referenced Series Sequence — source CT series const referencedSeriesSq = makeElement('SQ', { [tagKey(0x00_20, 0x00_0e)]: makeElement('UI', sourceSeriesUID) }); // (0008,2112) Source Image Sequence — one item per source CT instance const sourceImgSeq = makeElement('SQ', ...sourceInstanceUIDs.map(uid => ({ [tagKey(0x00_08, 0x11_50)]: makeElement('UI', CT_SOP_CLASS), [tagKey(0x00_08, 0x11_55)]: makeElement('UI', uid) }))); let previewRows; let previewCols; let pixelData; if (options.previewPixels) { const inferredSize = Math.round(Math.sqrt(options.previewPixels.length / 3)); previewRows = options.previewRows ?? inferredSize; previewCols = options.previewCols ?? inferredSize; if (options.previewPixels.length !== previewRows * previewCols * 3) { throw new Error(`previewPixels length ${options.previewPixels.length} does not match ${previewRows}×${previewCols}×3`); } pixelData = options.previewPixels; } else { previewRows = options.previewRows ?? 128; previewCols = options.previewCols ?? 128; pixelData = new Uint8Array(previewRows * previewCols * 3); } const d = instanceCreationDate; const t = instanceCreationTime; const dt = d + t; const pt = resolvePatientTagFallbacks(options); const sr = resolveSeriesTagFallbacks(options, d, t); // ── 4. Assemble the dataset ─────────────────────────────────────────────── const dataset = { // 0008 group [tagKey(0x00_08, 0x00_05)]: makeElement('CS', 'ISO_IR 192'), [tagKey(0x00_08, 0x00_08)]: makeElement('CS', 'DERIVED', 'SECONDARY'), [tagKey(0x00_08, 0x00_12)]: makeElement('DA', d), [tagKey(0x00_08, 0x00_13)]: makeElement('TM', t), [tagKey(0x00_08, 0x00_16)]: makeElement('UI', SC_SOP_CLASS), [tagKey(0x00_08, 0x00_18)]: makeElement('UI', sopInstanceUID), [tagKey(0x00_08, 0x00_20)]: makeElement('DA', pt.studyDate), [tagKey(0x00_08, 0x00_21)]: makeElement('DA', sr.seriesDate), [tagKey(0x00_08, 0x00_30)]: makeElement('TM', pt.studyTime), [tagKey(0x00_08, 0x00_31)]: makeElement('TM', sr.seriesTime), [tagKey(0x00_08, 0x00_50)]: makeElement('SH', pt.accessionNumber), [tagKey(0x00_08, 0x00_60)]: makeElement('CS', 'OT'), [tagKey(0x00_08, 0x00_64)]: makeElement('CS', 'WSD'), [tagKey(0x00_08, 0x00_70)]: makeElement('LO', 'Tomoverse Imaging'), [tagKey(0x00_08, 0x02_01)]: makeElement('SH', formatTimezoneOffset()), [tagKey(0x00_08, 0x10_30)]: makeElement('LO', pt.studyDescription), [tagKey(0x00_08, 0x10_3e)]: makeElement('LO', seriesDescription), [tagKey(0x00_08, 0x10_70)]: makeElement('PN', author), [tagKey(0x00_08, 0x10_90)]: makeElement('LO', 'tvCT'), [tagKey(0x00_08, 0x11_15)]: referencedSeriesSq, [tagKey(0x00_08, 0x21_11)]: makeElement('ST', 'tvCT worksession preview and private analysis state derived from source CT images.'), [tagKey(0x00_08, 0x21_12)]: sourceImgSeq, // 0010 group [tagKey(0x00_10, 0x00_10)]: makeElement('PN', pt.patientName), [tagKey(0x00_10, 0x00_20)]: makeElement('LO', pt.patientID), [tagKey(0x00_10, 0x00_30)]: makeElement('DA', pt.patientBirthDate), [tagKey(0x00_10, 0x00_40)]: makeElement('CS', pt.patientSex), // 0018 group [tagKey(0x00_18, 0x10_12)]: makeElement('DA', d), [tagKey(0x00_18, 0x10_14)]: makeElement('TM', t), [tagKey(0x00_18, 0x10_16)]: makeElement('LO', 'Tomoverse Imaging'), [tagKey(0x00_18, 0x10_18)]: makeElement('LO', 'tvCT'), [tagKey(0x00_18, 0x10_19)]: makeElement('LO', softwareVersion), [tagKey(0x00_18, 0x10_20)]: makeElement('LO', softwareVersion), // 0020 group [tagKey(0x00_20, 0x00_0d)]: makeElement('UI', studyInstanceUID), [tagKey(0x00_20, 0x00_0e)]: makeElement('UI', seriesInstanceUID), [tagKey(0x00_20, 0x00_10)]: makeElement('SH', pt.studyID), [tagKey(0x00_20, 0x00_11)]: makeElement('IS', sr.seriesNumber), [tagKey(0x00_20, 0x00_13)]: makeElement('IS', 1), // 0028 group [tagKey(0x00_28, 0x00_02)]: makeElement('US', 3), [tagKey(0x00_28, 0x00_04)]: makeElement('CS', 'RGB'), [tagKey(0x00_28, 0x00_06)]: makeElement('US', 0), [tagKey(0x00_28, 0x00_10)]: makeElement('US', previewRows), [tagKey(0x00_28, 0x00_11)]: makeElement('US', previewCols), [tagKey(0x00_28, 0x01_00)]: makeElement('US', 8), [tagKey(0x00_28, 0x01_01)]: makeElement('US', 8), [tagKey(0x00_28, 0x01_02)]: makeElement('US', 7), [tagKey(0x00_28, 0x01_03)]: makeElement('US', 0), [tagKey(0x00_28, 0x03_01)]: makeElement('CS', 'NO'), [tagKey(0x00_28, 0x21_10)]: makeElement('CS', '00'), // 0029 group — TOMOVERSE_TVCT_1 private block [tagKey(0x00_29, 0x00_10)]: makeElement('LO', PRIVATE_CREATOR), [tagKey(0x00_29, 0x10_01)]: makeElement('LO', 'TVCT_WORKSESSION'), [tagKey(0x00_29, 0x10_02)]: makeElement('LO', payloadSchemaVersion), [tagKey(0x00_29, 0x10_03)]: makeElement('LO', workSessionUID), [tagKey(0x00_29, 0x10_04)]: makeElement('UL', workSessionRevision), [tagKey(0x00_29, 0x10_05)]: makeElement('CS', 'JSON'), [tagKey(0x00_29, 0x10_06)]: makeElement('CS', 'GZIP'), [tagKey(0x00_29, 0x10_07)]: makeElement('UL', originalLength), [tagKey(0x00_29, 0x10_08)]: makeElement('UT', `sha256:${sha256}`), [tagKey(0x00_29, 0x10_09)]: payloadSq, [tagKey(0x00_29, 0x10_11)]: makeElement('LO', authorUserId || author), [tagKey(0x00_29, 0x10_12)]: makeElement('PN', author), [tagKey(0x00_29, 0x10_13)]: makeElement('DT', dt), // Private mirror of the standard (300E) review tags, in case a PACS drops non-indexed attributes. [tagKey(0x00_29, 0x10_14)]: makeElement('CS', reviewStatus), [tagKey(0x00_29, 0x10_15)]: makeElement('LO', reviewerUserId), [tagKey(0x00_29, 0x10_16)]: makeElement('PN', reviewerName), [tagKey(0x00_29, 0x10_17)]: makeElement('DT', reviewDateTime), [tagKey(0x00_29, 0x10_18)]: makeElement('UT', reviewComment), [tagKey(0x00_29, 0x10_1d)]: makeElement('LO', reviewReasonCode), [tagKey(0x00_29, PRIVATE_TAG_PHASE_LABEL)]: makeElement('LO', phaseLabel), [tagKey(0x00_29, PRIVATE_TAG_SOURCE_INSTANCE_UIDS)]: makeElement('UT', sourceInstanceUIDs.join('\\')), [tagKey(0x00_29, PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION)]: makeElement('LO', sourceSeriesDescription), [tagKey(0x00_29, PRIVATE_TAG_SOURCE_SERIES_UID)]: makeElement('UI', sourceSeriesUID), // 0070 group [tagKey(0x00_70, 0x00_84)]: makeElement('PN', author), // 300E group — standard approval/review module [tagKey(0x30_0e, 0x00_02)]: makeElement('CS', reviewStatus), [tagKey(0x30_0e, 0x00_04)]: makeElement('DA', reviewDate), [tagKey(0x30_0e, 0x00_05)]: makeElement('TM', reviewTime), [tagKey(0x30_0e, 0x00_08)]: makeElement('PN', reviewerName), // 7FE0 group — RGB pixel data (128×128 when captured, black placeholder otherwise) [tagKey(0x7f_e0, 0x00_10)]: makeObElement(pixelData) }; // ── 5. File meta (group 0002); dcmjs computes the group length and preamble ─ const meta = { [tagKey(0x00_02, 0x00_01)]: makeObElement(new Uint8Array([0x00, 0x01])), [tagKey(0x00_02, 0x00_02)]: makeElement('UI', SC_SOP_CLASS), [tagKey(0x00_02, 0x00_03)]: makeElement('UI', sopInstanceUID), [tagKey(0x00_02, 0x00_10)]: makeElement('UI', EXPLICIT_VR_LE), [tagKey(0x00_02, 0x00_12)]: makeElement('UI', IMPL_CLASS_UID), [tagKey(0x00_02, 0x00_13)]: makeElement('SH', IMPL_VERSION) }; // ── 6. Emit preamble + DICM + file-meta + dataset via dcmjs ──────────────── // dcmjs is loaded on demand so it stays out of the initial bundle — it is only // needed here, on an explicit export, not on the (dicom-parser) read path. const { default: dcmjs } = yield __webpack_require__.e(/*! import() */ "default-node_modules_dcmjs_build_dcmjs_es_js").then(__webpack_require__.bind(__webpack_require__, /*! dcmjs */ 545)); const dicomDict = new dcmjs.data.DicomDict(meta); dicomDict.dict = dataset; return dicomDict.write(); }); return _buildScOtDicom.apply(this, arguments); } function elementKey(group, element) { return `x${tagKey(group, element).toLowerCase()}`; } /** Parse a DICOM binary, returning `undefined` for input dicom-parser cannot read. */ function parseDataSet(dicomBuffer) { try { return dicom_parser__WEBPACK_IMPORTED_MODULE_1___default().parseDicom(new Uint8Array(dicomBuffer)); } catch { return undefined; } } /** Decode a single element's raw value bytes to text (null-stripped, trimmed). */ function decodeElement(dataSet, element) { const raw = dataSet.byteArray.slice(element.dataOffset, element.dataOffset + element.length); return new TextDecoder().decode(raw).replaceAll('\0', '').trim(); } /** Read a string-valued DICOM tag. Returns `undefined` if the tag is not found. */ function readDicomStringTag(dicomBuffer, targetGroup, targetElement) { const dataSet = parseDataSet(dicomBuffer); const element = dataSet?.elements[elementKey(targetGroup, targetElement)]; if (!dataSet || !element) return undefined; return decodeElement(dataSet, element); } /** Read the Modality tag (0008,0060) value from a DICOM binary. */ function readDicomModality(dicomBuffer) { return readDicomStringTag(dicomBuffer, 0x00_08, 0x00_60); } function looksLikeDicomUid(value) { return /^\d+(?:\.\d+)+$/.test(value); } function looksLikeDicomUidList(value) { const parts = value.split('\\').map(v => v.trim()).filter(v => v.length > 0); return parts.length > 0 && parts.every(part => looksLikeDicomUid(part)); } function parseUidList(value) { return value.split('\\').filter(v => v.length > 0); } function resolveSourceSeriesUid(read, dataSet) { const legacySourceSeriesUid = read(0x00_29, PRIVATE_TAG_PHASE_LABEL); return read(0x00_29, PRIVATE_TAG_SOURCE_SERIES_UID) || (looksLikeDicomUid(legacySourceSeriesUid) ? legacySourceSeriesUid : '') || readSequenceUid(dataSet, 0x00_08, 0x11_15, 0x00_20, 0x00_0e); } function resolveSourceSeriesDescription(read) { const candidate = read(0x00_29, PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION); return candidate.length > 0 && !looksLikeDicomUidList(candidate) ? candidate : read(0x00_29, LEGACY_PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION); } function resolveSourceInstanceUids(read, dataSet) { const descriptionCandidate = read(0x00_29, PRIVATE_TAG_SOURCE_SERIES_DESCRIPTION); const storedValue = read(0x00_29, PRIVATE_TAG_SOURCE_INSTANCE_UIDS) || (looksLikeDicomUidList(descriptionCandidate) ? descriptionCandidate : read(0x00_29, LEGACY_PRIVATE_TAG_SOURCE_INSTANCE_UIDS)); if (storedValue) return parseUidList(storedValue); return readSequenceUids(dataSet, 0x00_08, 0x21_12, 0x00_08, 0x11_55); } /** Read the first item of a SQ tag and return one child tag value as a string. */ function readSequenceUid(dataSet, sqGroup, sqElement, childGroup, childElement) { const sq = dataSet.elements[elementKey(sqGroup, sqElement)]; const itemSet = sq?.items?.[0]?.dataSet; if (!itemSet) return ''; const element = itemSet.elements[elementKey(childGroup, childElement)]; return element ? decodeElement(itemSet, element) : ''; } /** Read a SQ tag and return the given child tag value from every item. */ function readSequenceUids(dataSet, sqGroup, sqElement, childGroup, childElement) { const sq = dataSet.elements[elementKey(sqGroup, sqElement)]; const uids = []; for (const item of sq?.items ?? []) { const itemSet = item.dataSet; if (!itemSet) continue; const element = itemSet.elements[elementKey(childGroup, childElement)]; if (element) uids.push(decodeElement(itemSet, element)); } return uids; } /** Reassemble the chunked payload from the private (0029,1009) sequence, ordered by chunk index. */ function readChunkedPayload(sequence) { const chunks = []; for (const item of sequence.items ?? []) { const itemSet = item.dataSet; const payload = itemSet?.elements[elementKey(0x00_29, 0x10_24)]; if (!itemSet || !payload) continue; const actualLength = itemSet.uint32(elementKey(0x00_29, 0x10_23)) ?? payload.length; const index = itemSet.uint32(elementKey(0x00_29, 0x10_21)) ?? 0; chunks.push({ data: itemSet.byteArray.slice(payload.dataOffset, payload.dataOffset + actualLength), index }); } if (chunks.length === 0) return undefined; const ordered = chunks.toSorted((a, b) => a.index - b.index).map(c => c.data); const total = ordered.reduce((sum, c) => sum + c.length, 0); const result = new Uint8Array(total); let pos = 0; for (const chunk of ordered) { result.set(chunk, pos); pos += chunk.length; } return result; } /** * Read the TOMOVERSE_TVCT_1 (0029) private block from a DICOM binary and return the * annotation payload bytes plus author/source metadata. * Returns `undefined` when the private creator tag or payload sequence is absent. */ function extractAnnotationTags(dicomBuffer) { const dataSet = parseDataSet(dicomBuffer); if (!dataSet) return undefined; const creator = dataSet.elements[elementKey(0x00_29, 0x00_10)]; if (!creator || decodeElement(dataSet, creator) !== PRIVATE_CREATOR) return undefined; const sequence = dataSet.elements[elementKey(0x00_29, 0x10_09)]; const payloadBytes = sequence ? readChunkedPayload(sequence) : undefined; if (!payloadBytes) return undefined; const read = (group, element) => { const found = dataSet.elements[elementKey(group, element)]; return found ? decodeElement(dataSet, found) : ''; }; const sourceSeriesUid = resolveSourceSeriesUid(read, dataSet); const sourceSeriesDescription = resolveSourceSeriesDescription(read); const sourceInstanceUids = resolveSourceInstanceUids(read, dataSet); // Prefer the standard ApprovalStatus (300E,0002); fall back to the private mirror. const reviewStatus = read(0x30_0e, 0x00_02) || read(0x00_29, 0x10_14); return { creatorName: read(0x00_29, 0x10_12), creatorUserId: read(0x00_29, 0x10_11), payloadBytes, phaseLabel: read(0x00_29, PRIVATE_TAG_PHASE_LABEL), reviewComment: read(0x00_29, 0x10_18), reviewDateTime: read(0x00_29, 0x10_17), reviewerName: read(0x00_29, 0x10_16), reviewerUserId: read(0x00_29, 0x10_15), reviewReasonCode: read(0x00_29, 0x10_1d), reviewStatus, sourceInstanceUids, sourceSeriesDescription, sourceSeriesUid, workSessionRevision: dataSet.uint32(elementKey(0x00_29, 0x10_04)) ?? 0 }; } /***/ }, /***/ 8027 /*!******************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/services/dicom-export.service.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomExportService: () => (/* binding */ DicomExportService), /* harmony export */ TAVI_PROTOCOL_ID: () => (/* reexport safe */ _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.TAVI_PROTOCOL_ID) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./dicom-annotation-codec */ 19462); const UID_ROOT = '1.3.6.1.4.1.66095'; function generateUid() { const buf = crypto.getRandomValues(new Uint32Array(4)); let n = 0n; for (const v of buf) n = n << 32n | BigInt(v >>> 0); return `${UID_ROOT}.${n}`; } /** * Derive a deterministic DICOM UID from an arbitrary string via SHA-256. * Same input always yields the same Tomoverse-rooted UID. */ function deterministicUid(_x) { return _deterministicUid.apply(this, arguments); } function _deterministicUid() { _deterministicUid = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (input) { const hash = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(input)); const bytes = new Uint8Array(hash).slice(0, 16); let n = 0n; for (const b of bytes) { n = n << 8n | BigInt(b); } return `${UID_ROOT}.${n}`; }); return _deterministicUid.apply(this, arguments); } function formatDate(d) { const mm = String(d.getMonth() + 1).padStart(2, '0'); const dd = String(d.getDate()).padStart(2, '0'); return `${d.getFullYear()}${mm}${dd}`; } function formatTime(d) { const hh = String(d.getHours()).padStart(2, '0'); const min = String(d.getMinutes()).padStart(2, '0'); const ss = String(d.getSeconds()).padStart(2, '0'); return `${hh}${min}${ss}`; } /** No review → UNAPPROVED at revision 0; a review stamps the decision + increments the revision. */ function resolveReviewFields(review, now) { if (!review) { return { reviewComment: '', reviewDate: '', reviewDateTime: '', reviewerName: '', reviewerUserId: '', reviewReasonCode: '', reviewStatus: 'UNAPPROVED', reviewTime: '', workSessionRevision: 0 }; } const reviewDate = formatDate(now); const reviewTime = formatTime(now); return { reviewComment: review.comment, reviewDate, reviewDateTime: reviewDate + reviewTime, reviewerName: review.reviewerName, reviewerUserId: review.reviewerUserId, reviewReasonCode: review.reasonCode ?? '', reviewStatus: review.status, reviewTime, workSessionRevision: review.baseRevision + 1 }; } /** Extract patient / study demographics from a raw WADO-RS metadata JSON object. */ function extractDemographics(meta) { if (!meta) return {}; const tagValue = tag => meta[tag]?.Value?.[0] ?? ''; return { accessionNumber: tagValue('00080050'), patientBirthDate: tagValue('00100030'), patientID: tagValue('00100020'), patientName: meta['00100010']?.Value?.[0]?.Alphabetic ?? '', patientSex: tagValue('00100040'), studyDate: tagValue('00080020'), studyDescription: tagValue('00081030'), studyID: tagValue('00200010'), studyTime: tagValue('00080030') }; } function computeMaxSeriesNumber(studySeries) { let max = 0; for (const s of studySeries ?? []) { if (typeof s.seriesNumber === 'number' && s.seriesNumber > max) max = s.seriesNumber; } return max; } class DicomExportService { db = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_3__.DicomDatabaseService); api = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_3__.DicomApiService); env = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.ENV); state = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)('idle', ...(ngDevMode ? [{ debugName: "state" }] : [])); error = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "error" }] : [])); /** * Derives the OT series identity from (work session, analysis name), so the series * follows the name shown at export time rather than colliding across renames. * Deterministic: every export under the same name — first or repeated — lands on the * same series, since identity can't depend on whether a rename "just happened". */ deriveRenamedWorkSessionUid(originalWorkSessionUid, newName) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return deterministicUid(`${originalWorkSessionUid}:${newName}`); })(); } /** * Build and upload a new OT DICOM file for each source series. * The file is built from scratch (no CT binary fetched) using WADO-RS instance * metadata for demographics and the given annotation payload. */ exportSeriesToStore(options) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { activePhaseInstanceUIDs = [], annotations = [], author = '', authorUserId = '', calculatedPaths = {}, destinationStoreUid, existingOtSeriesUid, phaseLabel = '', previewPixels, protocolBindings = [], protocolFormValues, renderSettings2D, renderSettings3D, review, seriesUids, sourceStudyUid = '', storeUid, workSessionName = '', workSessionUID = '' } = options; _this.state.set('exporting'); _this.error.set(undefined); try { for (const [seriesIndex, seriesUid] of seriesUids.entries()) { yield _this.exportOneSeries(seriesUid, seriesIndex, { activePhaseInstanceUIDs, annotations, author, authorUserId, calculatedPaths, destinationStoreUid: destinationStoreUid ?? storeUid, existingOtSeriesUid, phaseLabel, previewPixels, protocolBindings, protocolFormValues, renderSettings2D, renderSettings3D, review, sourceStudyUid, storeUid, workSessionName, workSessionUID }); } _this.state.set('done'); } catch (error) { _this.error.set(error.message ?? String(error)); _this.state.set('error'); throw error; } })(); } /** Record a review decision as a new OT instance in the same series (creator preserved, current user = reviewer). */ reviewSeriesToStore(parameters) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { context } = parameters; yield _this2.exportSeriesToStore({ activePhaseInstanceUIDs: context.activePhaseInstanceUIDs, annotations: parameters.annotations ?? [], author: context.creatorName, authorUserId: context.creatorUserId, calculatedPaths: parameters.calculatedPaths ?? {}, phaseLabel: context.phaseLabel, previewPixels: parameters.previewPixels, protocolBindings: parameters.protocolBindings ?? [], protocolFormValues: parameters.protocolFormValues, review: { baseRevision: context.revision, comment: parameters.comment, reasonCode: parameters.reasonCode, reviewerName: parameters.reviewerName, reviewerUserId: parameters.reviewerUserId, status: parameters.status }, seriesUids: [context.sourceSeriesUid], sourceStudyUid: context.studyUid, storeUid: context.storeUid, workSessionName: context.workSessionName, workSessionUID: context.workSessionUid }); })(); } exportOneSeries(seriesUid, seriesIndex, options) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { activePhaseInstanceUIDs, annotations, author, authorUserId, calculatedPaths, destinationStoreUid, existingOtSeriesUid, phaseLabel, previewPixels, protocolBindings, protocolFormValues, renderSettings2D, renderSettings3D, review, sourceStudyUid, storeUid, workSessionName, workSessionUID } = options; // Authoritative study UID from local cache; fall back to the route param. const localStudyUid = yield _this3.db.getStudyUidForSeries(seriesUid); const studyUid = localStudyUid ?? sourceStudyUid; if (!studyUid) { throw new Error('Could not determine study UID for series. Please reload the viewer and try again.'); } // Series UID is deterministic per (work session, source series): all exports // of the same analysis group under one OT series; different analyses each // get their own series even when they reference the same source CT. const newSeriesUid = existingOtSeriesUid ?? (yield deterministicUid(workSessionUID + seriesUid)); // Instance UID is always fresh so each upload creates a new DICOM instance. const now = new Date(); const newInstanceUid = generateUid(); // Fetch study series (from the destination store) to compute the next available series number. let studySeries; try { studySeries = yield _this3.db.getSeriesForStudy(studyUid, destinationStoreUid); } catch { // Non-fatal — fall back to series number 1 } const existingOtSeries = studySeries?.find(s => s.seriesInstanceUID === newSeriesUid); const maxSeriesNumber = computeMaxSeriesNumber(studySeries); const seriesNumber = typeof existingOtSeries?.seriesNumber === 'number' ? existingOtSeries.seriesNumber : maxSeriesNumber + 1 + seriesIndex; // Fetch instance metadata (no binary download needed). const instances = yield _this3.db.getSeriesInstancesMetadata(studyUid, seriesUid, storeUid); if (instances.length === 0) { throw new Error('Series could not be cached before export. Please cache the series first and try again.'); } const sourceInstanceUIDs = activePhaseInstanceUIDs.length > 0 ? activePhaseInstanceUIDs : instances.map(inst => inst.sopInstanceUID).filter(Boolean); // Pull patient / study demographics from the first instance's WADO-RS metadata. const firstMeta = instances[0].toJSON?.()?.metadata; const demographics = extractDemographics(firstMeta); const sourceSeriesDescription = String(firstMeta?.['0008103E']?.Value?.[0] ?? '').trim(); // Normalize the TAVI snapshot before writing so an OT can always be read by // the same constrained payload schema used for external imports. const payload = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__.annotationPayloadV1Schema.parse({ annotationProtocolBindings: protocolBindings, annotations, calculatedPaths, protocolFormValues, renderSettings2D, renderSettings3D, sourceInstanceUIDs, sourceSeriesUID: seriesUid, version: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__.OT_PAYLOAD_LATEST_VERSION }); const otInstance = yield (0,_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__.buildScOtDicom)({ ...demographics, ...resolveReviewFields(review, now), author, authorUserId, instanceCreationDate: formatDate(now), instanceCreationTime: formatTime(now), payload, payloadSchemaVersion: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_2__.OT_PAYLOAD_SCHEMA_VERSION, phaseLabel: phaseLabel || undefined, previewPixels, seriesDescription: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.toTvctWorkSessionDescription)(workSessionName), seriesInstanceUID: newSeriesUid, seriesNumber, softwareVersion: _this3.env.version ?? '0.0.0', sopInstanceUID: newInstanceUid, sourceInstanceUIDs, sourceSeriesDescription, sourceSeriesUID: seriesUid, studyInstanceUID: studyUid, workSessionUID }); yield _this3.api.uploadToStore([otInstance], destinationStoreUid); yield _this3.verifyExportIntegrity(otInstance, newInstanceUid, studyUid, newSeriesUid, destinationStoreUid); // Best-effort: cache locally so the viewer can open immediately without WADO-RS. try { const remoteInstances = yield _this3.api.getInstancesForSeries(studyUid, newSeriesUid, destinationStoreUid); yield _this3.db.saveInstances(remoteInstances, studyUid, newSeriesUid, destinationStoreUid); yield _this3.db.saveBinary(newInstanceUid, otInstance, destinationStoreUid); } catch { // Non-fatal — viewer falls back to WADO-RS once the store has indexed. } })(); } /** * Downloads the just-uploaded OT instance back from the store and verifies its * annotation tags are intact. Throws if the round-trip corrupts or strips the * private-tag payload — this surfaces store-side degradation (e.g. transcoding * that drops private tags) as an explicit export error rather than a silent * broken file. * * Uses the locally-built buffer as the source of truth when the store has not * indexed the instance yet (Google Healthcare can take a few seconds). */ verifyExportIntegrity(localBuffer, instanceUid, studyUid, seriesUid, storeUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { let buffer = localBuffer; try { const remote = yield _this4.api.getInstanceDicomFile(studyUid, seriesUid, instanceUid, storeUid); buffer = remote instanceof SharedArrayBuffer ? localBuffer : remote; } catch { // Store may not have indexed yet — fall back to verifying the local build. } const tags = (0,_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__.extractAnnotationTags)(buffer); if (!tags) { throw new Error('Export integrity check failed: annotation private tags are missing from the stored OT file. ' + 'The DICOM store may have stripped private tags during upload.'); } })(); } /** * Read annotation data embedded in a DICOM file and deserialize the payload. * Returns undefined if the file is not an OT DICOM with TOMOVERSE private tags. */ importAnnotationsFromDicom(dicomBuffer) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if ((0,_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__.readDicomModality)(dicomBuffer) !== 'OT') return undefined; const tags = (0,_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__.extractAnnotationTags)(dicomBuffer); if (!tags) return undefined; return (0,_dicom_annotation_codec__WEBPACK_IMPORTED_MODULE_6__.deserializeAnnotationPayload)(tags.payloadBytes); })(); } static ɵfac = function DicomExportService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomExportService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: DicomExportService, factory: DicomExportService.ɵfac }); } /***/ }, /***/ 14043 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/services/dicom-importer.service.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 32348); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 53291); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../logging/utils */ 14337); /* harmony import */ var _components_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../components/patient-library/patient-library-list.facade */ 67045); const SERIES_REFRESH_THROTTLE_MS = 250; class DicomImporterDialogService { db = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.DicomDatabaseService); api = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.DicomApiService); storeList = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_9__.DicomStoreListService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_8__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__.TranslateService); libraryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_components_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_11__.PatientLibraryListFacade); static log; isImportingToLibrary = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "isImportingToLibrary" }] : [])); series = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_2__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_2__.toObservable)(this.libraryFacade.selectedStoreUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.switchMap)(storeUid => this.db.getAllNotUploadedSeries(storeUid ?? '')), (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.throttleTime)(SERIES_REFRESH_THROTTLE_MS, rxjs__WEBPACK_IMPORTED_MODULE_3__.asyncScheduler, { leading: true, trailing: true }), // Absent display values stay empty so the table renders NO_DATA_PLACEHOLDER. (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.map)(seriesList => seriesList.map(seriesDocument => ({ images: seriesDocument.instances.length, modality: seriesDocument.modality ?? '', patientID: seriesDocument.patientID ?? '', patientName: seriesDocument.patientName ?? '', seriesDescription: seriesDocument.seriesDescription ?? '', seriesInstanceUID: seriesDocument.seriesInstanceUID, seriesNumber: seriesDocument.seriesNumber ?? 0, studyDate: seriesDocument.studyDate ?? '', studyDescription: seriesDocument.studyDescription ?? '', studyInstanceUID: seriesDocument.studyInstanceUID })))), { initialValue: [] }); constructor() { if (!DicomImporterDialogService.log) { DicomImporterDialogService.log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_10__.getLogger)(DicomImporterDialogService.name); } } /** * Returns the UID of the store the importer is currently working against. */ resolveCurrentStore() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this.libraryFacade.selectedStoreUid() ?? (yield _this.storeList.resolveStoreUid()); })(); } toUploadErrorMessage(error) { const serverMessage = error?.error?.message; if (serverMessage && /permission|denied|forbidden/i.test(serverMessage)) { return this.translate.instant('dicomImporter.importToast.permissionDenied'); } return serverMessage ?? this.translate.instant('dicomImporter.importToast.uploadFailed'); } importToLibrary(rows) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this2.isImportingToLibrary.set(true); try { const storeUid = yield _this2.resolveCurrentStore(); const uploadedSeriesUids = []; for (const row of rows) { const seriesUid = row.seriesInstanceUID; if (!seriesUid) continue; try { const files = yield _this2.db.getSeriesInstanceFiles(seriesUid, storeUid); // A file whose attachment write failed leaves an instance without cached // pixel data. Uploading the rest would store an incomplete series. if (files.length === 0 || files.length < row.images) { _this2.messageService.add({ life: 4000, severity: 'warn', summary: _this2.translate.instant('dicomImporter.importToast.noFiles') }); continue; } yield _this2.api.uploadToStore(files, storeUid); uploadedSeriesUids.push(seriesUid); _this2.messageService.add({ life: 3000, severity: 'success', summary: _this2.translate.instant('dicomImporter.importToast.success') }); } catch (error) { DicomImporterDialogService.log?.error('Import to library failed', error); _this2.messageService.add({ detail: _this2.toUploadErrorMessage(error), life: 6000, severity: 'error', summary: _this2.translate.instant('dicomImporter.importToast.error') }); } } if (uploadedSeriesUids.length > 0) { _this2.deleteUploadedSeriesInBackground(uploadedSeriesUids); _this2.libraryFacade.reloadStudies(); } return uploadedSeriesUids; } finally { _this2.isImportingToLibrary.set(false); } })(); } /** * Deletes the staged local copies of the given series from the store the * importer is currently working against. */ deleteStagedSeries(seriesUids) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const storeUid = yield _this3.resolveCurrentStore(); yield Promise.all(seriesUids.map(uid => _this3.db.deleteLocalSeries(uid, storeUid))); })(); } deleteUploadedSeriesInBackground(seriesUids) { this.deleteStagedSeries(seriesUids).catch(error => { DicomImporterDialogService.log?.error('Failed to delete staged series after upload', error); }); } getSeriesInstancesMetadata(studyUid, seriesUid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this4.db.getSeriesInstancesMetadata(studyUid, seriesUid, yield _this4.resolveCurrentStore()); })(); } getSeriesCommonMetadata(studyUid, seriesUid) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this5.db.getSeriesComputedMetadata(studyUid, seriesUid, yield _this5.resolveCurrentStore()); })(); } getSeriesImageUrls(studyUid, seriesUid) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this6.db.getSeriesImageUrls(studyUid, seriesUid, yield _this6.resolveCurrentStore()); })(); } static ɵfac = function DicomImporterDialogService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomImporterDialogService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: DicomImporterDialogService, factory: DicomImporterDialogService.ɵfac }); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DicomImporterDialogService); /***/ }, /***/ 59639 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/dicom-importer/services/protocol-binding-utils.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildProtocolBindings: () => (/* binding */ buildProtocolBindings), /* harmony export */ rebuildProtocolState: () => (/* binding */ rebuildProtocolState) /* harmony export */ }); function buildProtocolBindings(definitions, instances) { const definitionMap = Object.fromEntries(definitions.map(d => [d.id, d])); const bindings = []; for (const instance of instances) { const definition = definitionMap[instance.protocolId]; if (!definition) continue; for (const [placeholderId, annotationId] of Object.entries(instance.placeholderMappings)) { const placeholderIndex = definition.placeholders.findIndex(p => p.id === placeholderId); if (placeholderIndex === -1) continue; const placeholder = definition.placeholders[placeholderIndex]; if (!placeholder) continue; bindings.push({ annotationId, annotationType: placeholder.annotationType, color: placeholder.color, placeholderIndex, placeholderName: placeholder.name, protocolId: instance.protocolId, protocolName: definition.name, protocolPlaceholderId: placeholderId, role: placeholder.relationship == undefined ? '' : JSON.stringify(placeholder.relationship) }); } } return bindings; } /** * Reconstruct protocol definitions and instances from serialized bindings. * This is the inverse of `buildProtocolBindings` — call it during OT import to * restore the full protocol state that was captured at export time. */ function rebuildProtocolState(bindings) { const byProtocol = new Map(); for (const binding of bindings) { const group = byProtocol.get(binding.protocolId) ?? []; group.push(binding); byProtocol.set(binding.protocolId, group); } const definitions = []; const instances = []; for (const [protocolId, protocolBindings] of byProtocol) { const sorted = protocolBindings.toSorted((a, b) => a.placeholderIndex - b.placeholderIndex); const placeholders = sorted.map(b => { let relationship; if (b.role) { try { relationship = JSON.parse(b.role); } catch { // malformed role — omit relationship } } return { annotationType: b.annotationType, color: b.color, id: b.protocolPlaceholderId, name: b.placeholderName, ...(relationship === undefined ? {} : { relationship }) }; }); const protocolName = protocolBindings[0]?.protocolName ?? ''; definitions.push({ id: protocolId, name: protocolName, placeholders }); const placeholderMappings = {}; for (const b of protocolBindings) { placeholderMappings[b.protocolPlaceholderId] = b.annotationId; } instances.push({ placeholderMappings, protocolId }); } return { definitions, instances }; } /***/ }, /***/ 66039 /*!**************************************************************************!*\ !*** ./libs/feature/src/lib/dual-axis-slider/camera-slider.component.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CameraSliderComponent: () => (/* binding */ CameraSliderComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); class CameraSliderComponent { CCType = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.SliderSourceType.CCSLIDER; RLType = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.SliderSourceType.RLSLIDER; step = 1; isDarkMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(true, { ...(ngDevMode ? { debugName: "isDarkMode" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_0__.booleanAttribute }); //save current slider states ccSliderValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(0, ...(ngDevMode ? [{ debugName: "ccSliderValue" }] : [])); rlSliderValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(0, ...(ngDevMode ? [{ debugName: "rlSliderValue" }] : [])); ccChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); rlChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); didReset = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); rlSliderChanged(newValueRL) { this.rlChanged.emit(newValueRL); } ccSliderChanged(newValueCC) { this.ccChanged.emit(newValueCC); } resetAngulations(event) { this.didReset.emit(event); } static ɵfac = function CameraSliderComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CameraSliderComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: CameraSliderComponent, selectors: [["lib-camera-slider"]], inputs: { isDarkMode: [1, "isDarkMode"], ccSliderValue: [1, "ccSliderValue"], rlSliderValue: [1, "rlSliderValue"] }, outputs: { ccSliderValue: "ccSliderValueChange", rlSliderValue: "rlSliderValueChange", ccChanged: "ccChanged", rlChanged: "rlChanged", didReset: "didReset" }, decls: 1, vars: 12, consts: [["toolTipValue", "Reset", 3, "hSliderChanged", "vSliderChanged", "didReset", "hSliderType", "vSliderType", "cSliderStep", "hMaxValue", "hMinValue", "vMaxValue", "vMinValue", "vStartingValue", "hStartingValue", "vSliderValue", "hSliderValue", "isDarkMode"]], template: function CameraSliderComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "lib-corner-sliders", 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("hSliderChanged", function CameraSliderComponent_Template_lib_corner_sliders_hSliderChanged_0_listener($event) { return ctx.rlSliderChanged($event); })("vSliderChanged", function CameraSliderComponent_Template_lib_corner_sliders_vSliderChanged_0_listener($event) { return ctx.ccSliderChanged($event); })("didReset", function CameraSliderComponent_Template_lib_corner_sliders_didReset_0_listener($event) { return ctx.resetAngulations($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("hSliderType", ctx.RLType)("vSliderType", ctx.CCType)("cSliderStep", 0.05)("hMaxValue", 89)("hMinValue", -89)("vMaxValue", 89)("vMinValue", -89)("vStartingValue", 0)("hStartingValue", 0)("vSliderValue", ctx.ccSliderValue())("hSliderValue", ctx.rlSliderValue())("isDarkMode", ctx.isDarkMode()); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.CornerSlidersComponent], encapsulation: 2 }); } /***/ }, /***/ 96472 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/imaging-library/imaging-library-page.component.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ImagingLibraryPageComponent: () => (/* binding */ ImagingLibraryPageComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/progressspinner */ 7271); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _dicom_importer_components_dicom_importer_dialog_dicom_importer_dialog_component__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../dicom-importer/components/dicom-importer-dialog/dicom-importer-dialog.component */ 18809); /* harmony import */ var _dicom_importer_components_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../dicom-importer/components/patient-library/patient-library-list.facade */ 67045); /* harmony import */ var _dicom_importer_components_patient_library_patient_library_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../dicom-importer/components/patient-library/patient-library.component */ 22357); /* harmony import */ var _dicom_importer_components_patient_library_series_cache_tasks_component__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../dicom-importer/components/patient-library/series-cache-tasks.component */ 8487); /* harmony import */ var _dicom_importer_components_patient_library_series_cache_service__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../dicom-importer/components/patient-library/series-cache.service */ 60240); /* harmony import */ var _dicom_importer_services_dicom_importer_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../dicom-importer/services/dicom-importer.service */ 14043); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _work_session_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../work-session/work-session-dialog.service */ 35009); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @angular/core */ 14975); function ImagingLibraryPageComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](1, "p-progressSpinner", 13); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](2, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](4, 1, "dicomImporter.exportToStoreDialog.checkingStores")); } } function ImagingLibraryPageComponent_Conditional_7_Conditional_15_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 22)(1, "div", 23); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](2, "i", 24); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](3, "div", 25)(4, "div", 26); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](6, "div", 15); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](9, "div", 27)(10, "div", 28)(11, "div", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](13, "div", 30); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](15, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](16, "div", 28)(17, "div", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](18); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](19, "div", 30); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](20); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](21, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](22, "div", 31)(23, "div", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](25, "libFileSize"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](26, "div", 30); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](27); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](28, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](29, "div", 32)(30, "span", 33); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](31); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](32, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](33, "span", 34); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](34, "DICOMweb"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](35, "span", 33); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](36); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](37, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](38, "span", 35, 3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](40); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { let tmp_10_0; let tmp_12_0; let tmp_14_0; const store_r6 = ctx; const urlTip_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](39); const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵclassMap"](ctx_r4.storeIcon(store_r6)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](store_r6.name); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](8, 14, ctx_r4.storeKindKey(store_r6))); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", ((tmp_10_0 = ctx_r4.storeStats()) == null ? null : tmp_10_0.studyCount) ?? "\u2014", " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](15, 16, "imagingLibrary.storeInfo.studies"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", ((tmp_12_0 = ctx_r4.storeStats()) == null ? null : tmp_12_0.seriesCount) ?? "\u2014", " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](21, 18, "imagingLibrary.storeInfo.series"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](25, 20, (tmp_14_0 = ctx_r4.storeStats()) == null ? null : tmp_14_0.totalSizeBytes), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](28, 22, "imagingLibrary.storeInfo.totalSize"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](32, 24, "imagingLibrary.storeInfo.protocol"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](37, 26, "imagingLibrary.storeInfo.baseUrl"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", urlTip_r7.truncated() ? store_r6.url : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", store_r6.url, " "); } } function ImagingLibraryPageComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ImagingLibraryPageComponent_Conditional_7_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const storeMenu_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](6); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](storeMenu_r2.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](1, "i", 15); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](4, "i", 16); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](5, "p-menu", 17, 0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](7, "button", 18, 1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](10, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ImagingLibraryPageComponent_Conditional_7_Template_button_click_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const infoButton_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](8); const storeInfo_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](13); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](storeInfo_r4.toggle($event, infoButton_r3)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](11, "i", 19); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](12, "p-popover", 20, 2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("onShow", function ImagingLibraryPageComponent_Conditional_7_Template_p_popover_onShow_12_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r4.loadStoreStats()); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](14, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](15, ImagingLibraryPageComponent_Conditional_7_Conditional_15_Template, 41, 28); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { let tmp_5_0; let tmp_10_0; const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵclassMap"](ctx_r4.storeIcon(ctx_r4.selectedStore())); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", ((tmp_5_0 = ctx_r4.selectedStore()) == null ? null : tmp_5_0.name) ?? _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](3, 8, "patientList.store"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("model", ctx_r4.storeMenuItems())("popup", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](9, 10, "imagingLibrary.storeDetails")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](10, 12, "imagingLibrary.storeDetails")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](8); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"]((tmp_10_0 = ctx_r4.selectedStore()) ? 15 : -1, tmp_10_0); } } function ImagingLibraryPageComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](0, "p-progressBar", 36); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](1, "span", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](3, "span", 38); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](4, "%"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("showValue", false)("value", ctx_r4.totalProgress()); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](ctx_r4.totalProgress()); } } function ImagingLibraryPageComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "p-button", 39); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ImagingLibraryPageComponent_Conditional_11_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r8); const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r4.clearFilters()); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](1, 1, "patientList.filters.clear")); } } const STORE_TYPE_ICONS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.CLOUD]: 'pi pi-cloud', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.DICOM_WEB]: 'pi pi-globe', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.DIMSE]: 'pi pi-server' }; const STORE_KIND_KEYS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.CLOUD]: 'imagingLibrary.storeKind.cloud', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.DICOM_WEB]: 'imagingLibrary.storeKind.dicomweb', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_11__.StoreType.DIMSE]: 'imagingLibrary.storeKind.dimse' }; class ImagingLibraryPageComponent { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_20__.getLogger)(ImagingLibraryPageComponent.name); destroyRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef); nestedDialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DialogService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateService); importDialogRef; dicomImportService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__.DicomImportService); patientLibraryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_dicom_importer_components_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_15__.PatientLibraryListFacade); stores = this.patientLibraryFacade.stores; selectedStoreUid = this.patientLibraryFacade.selectedStoreUid; loadingStores = this.patientLibraryFacade.loadingStores; storeStats = this.patientLibraryFacade.storeStats; loading = this.patientLibraryFacade.loading; detailsToolbar = this.patientLibraryFacade.detailsToolbar; reloadDisabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.detailsToolbar()?.loading() ?? this.loading(), ...(ngDevMode ? [{ debugName: "reloadDisabled" }] : [])); selectedStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.stores().find(store => store.uid === this.selectedStoreUid()), ...(ngDevMode ? [{ debugName: "selectedStore" }] : [])); /** * Menu model grouped by store type in {@link STORE_TYPE_ORDER}, separated by dividers. * Per-store icons convey the category; there are no group labels. */ storeMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const selectedUid = this.selectedStoreUid(); const toItem = store => ({ command: () => this.onStoreChange(store.uid), icon: STORE_TYPE_ICONS[(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.storeTypeForVendor)(store.vendor)], label: store.name, styleClass: store.uid === selectedUid ? 'active-store' : '' }); return _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.STORE_TYPE_ORDER.map(type => this.stores().filter(store => (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.storeTypeForVendor)(store.vendor) === type)).filter(group => group.length > 0).flatMap((group, index) => { const items = group.map(store => toItem(store)); return index > 0 ? [{ separator: true }, ...items] : items; }); }, ...(ngDevMode ? [{ debugName: "storeMenuItems" }] : [])); totalProgress = this.dicomImportService.totalProgress; constructor() { this.patientLibraryFacade.init().catch(error => { this.log.error('Failed to load studies:', error); }); this.destroyRef.onDestroy(() => this.importDialogRef?.close()); } storeIcon(store) { return store ? STORE_TYPE_ICONS[(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.storeTypeForVendor)(store.vendor)] : 'pi pi-database'; } storeKindKey(store) { return STORE_KIND_KEYS[(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.storeTypeForVendor)(store.vendor)]; } clearFilters() { this.patientLibraryFacade.requestClearFilters(); } /** Reloads whichever view is open: the series list at study level, the study list otherwise. */ reload() { const details = this.detailsToolbar(); if (details) { details.reload(); } else { this.patientLibraryFacade.reloadStudies(); } } loadStoreStats() { this.patientLibraryFacade.loadStoreStats().catch(error => { this.log.error('Failed to load store statistics:', error); }); } onStoreChange(storeUid) { this.patientLibraryFacade.selectStore(storeUid).catch(error => { this.log.error('Failed to switch store:', error); }); } openImportDialog() { this.importDialogRef = this.nestedDialogService.open(_dicom_importer_components_dicom_importer_dialog_dicom_importer_dialog_component__WEBPACK_IMPORTED_MODULE_14__.DicomImporterDialogComponent, { ..._dicom_importer_components_dicom_importer_dialog_dicom_importer_dialog_component__WEBPACK_IMPORTED_MODULE_14__.DICOM_IMPORTER_DIALOG_OPTIONS, header: this.translate.instant('dicomImporter.importDialog.header') }) ?? undefined; } static ɵfac = function ImagingLibraryPageComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ImagingLibraryPageComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵdefineComponent"]({ type: ImagingLibraryPageComponent, selectors: [["lib-imaging-library-page"]], hostAttrs: [1, "dark", "flex", "h-full", "flex-col", "bg-surface-950", "text-color"], features: [_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵProvidersFeature"]([primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DialogService, _dicom_importer_services_dicom_importer_service__WEBPACK_IMPORTED_MODULE_19__["default"], _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__.DicomImportService, _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__.VolumeLoaderService, _work_session_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_21__.WorkSessionDialogService, _dicom_importer_components_patient_library_patient_library_list_facade__WEBPACK_IMPORTED_MODULE_15__.PatientLibraryListFacade, // Above the library views: caching outlives the series screen, and the top bar hosts its tracker. _dicom_importer_components_patient_library_series_cache_service__WEBPACK_IMPORTED_MODULE_18__.SeriesCacheService, { provide: _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__.StudySearchProvider, useClass: _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_10__.ClientStudySearchProvider }])], decls: 16, vars: 10, consts: [["storeMenu", ""], ["infoButton", ""], ["storeInfo", ""], ["urlTip", "libEllipsisTip"], [1, "border-surface-800", "flex", "h-14", "shrink-0", "items-center", "gap-3", "border-b", "bg-(--p-app-chrome-page-header)", "px-5", "select-none"], [1, "font-semibold", "tracking-wide"], [1, "bg-surface-700", "mx-2", "h-6", "w-px"], [1, "flex", "items-center", "gap-1.5", "text-sm"], [1, "text-muted-color", "flex", "items-center", "gap-2", "px-2.5", "py-1.5"], [1, "grow"], ["data-test-id", "imaging-library-p-button-clear-filters", "icon", "pi pi-filter-slash", "severity", "secondary", "size", "small", "variant", "outlined", 3, "label"], ["data-test-id", "imaging-library-p-button-reload", "icon", "pi pi-refresh", "severity", "secondary", "size", "small", "variant", "outlined", 3, "click", "label", "disabled"], [1, "bg-surface-950", "min-h-0", "flex-1", "py-4"], ["strokeWidth", "4", 1, "size-4"], ["type", "button", "data-test-id", "imaging-library-button-store-menu", "aria-haspopup", "menu", 1, "hover:bg-surface-800", "flex", "cursor-pointer", "items-center", "gap-2", "rounded-md", "px-2.5", "py-1.5", "transition-colors", 3, "click"], [1, "text-muted-color", "text-xs"], [1, "pi", "pi-angle-down", "text-muted-color", "text-xs"], ["data-test-id", "imaging-library-p-menu-store", "appendTo", "body", 3, "model", "popup"], ["type", "button", "data-test-id", "imaging-library-button-store-info", "tooltipPosition", "bottom", 1, "text-muted-color", "hover:text-surface-300", "ml-1", "flex", "cursor-pointer", "items-center", "justify-center", 3, "click", "pTooltip"], [1, "pi", "pi-info-circle", "text-base"], [3, "onShow"], [1, "text-color", "w-72", "p-1"], [1, "flex", "items-center", "gap-3", "pb-3"], [1, "bg-primary-500/10", "border-primary-500/30", "flex", "h-10", "w-10", "shrink-0", "items-center", "justify-center", "rounded-md", "border"], [1, "text-primary-400"], [1, "min-w-0"], [1, "truncate", "font-semibold"], [1, "grid", "grid-cols-2", "gap-2", "pb-3"], [1, "bg-surface-800/70", "rounded-md", "py-2", "text-center"], [1, "text-base", "font-semibold", "tabular-nums"], [1, "text-muted-color", "text-[10px]", "tracking-wide", "uppercase"], [1, "bg-surface-800/70", "col-span-2", "rounded-md", "py-2", "text-center"], [1, "border-surface-700", "grid", "grid-cols-[auto_1fr]", "gap-x-4", "gap-y-1.5", "border-t", "pt-2.5", "text-xs"], [1, "text-muted-color"], [1, "text-right"], ["libEllipsisTip", "", "tooltipPosition", "bottom", 1, "min-w-0", "text-right", "font-mono", 3, "pTooltip"], ["styleClass", "h-2 w-24", 3, "showValue", "value"], [1, "w-8", "text-right", "text-sm"], [1, "text-sm"], ["data-test-id", "imaging-library-p-button-clear-filters", "icon", "pi pi-filter-slash", "severity", "secondary", "size", "small", "variant", "outlined", 3, "click", "label"]], template: function ImagingLibraryPageComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "header", 4)(1, "h1", 5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](4, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](5, "nav", 7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](6, ImagingLibraryPageComponent_Conditional_6_Template, 5, 3, "div", 8)(7, ImagingLibraryPageComponent_Conditional_7_Template, 16, 14); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](8, "div", 9)(9, "lib-series-cache-tasks"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](10, ImagingLibraryPageComponent_Conditional_10_Template, 5, 3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditionalCreate"](11, ImagingLibraryPageComponent_Conditional_11_Template, 2, 3, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](12, "p-button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipe"](13, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ImagingLibraryPageComponent_Template_p_button_click_12_listener() { return ctx.reload(); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](14, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](15, "lib-patient-library"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](3, 6, "imagingLibrary.title")); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx.loadingStores() ? 6 : 7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](ctx.totalProgress() > 0 && ctx.totalProgress() < 100 ? 10 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵconditional"](!ctx.detailsToolbar() ? 11 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpipeBind1"](13, 8, "patientList.reload"))("disabled", ctx.reloadDisabled()); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_3__.Button, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateModule, _dicom_importer_components_patient_library_patient_library_component__WEBPACK_IMPORTED_MODULE_16__.PatientLibraryComponent, primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_7__.ProgressBar, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__.ProgressSpinnerModule, primeng_progressspinner__WEBPACK_IMPORTED_MODULE_8__.ProgressSpinner, primeng_menu__WEBPACK_IMPORTED_MODULE_5__.Menu, primeng_popover__WEBPACK_IMPORTED_MODULE_6__.Popover, primeng_tooltip__WEBPACK_IMPORTED_MODULE_9__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_9__.Tooltip, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_13__.EllipsisTipDirective, _dicom_importer_components_patient_library_series_cache_tasks_component__WEBPACK_IMPORTED_MODULE_17__.SeriesCacheTasksComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_13__.FileSizePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 99957 /*!******************************************************************************!*\ !*** ./libs/feature/src/lib/imaging-library/live-analyses-page.component.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LiveAnalysesPageComponent: () => (/* binding */ LiveAnalysesPageComponent) /* harmony export */ }); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _dicom_importer_components_work_session_library_work_session_library_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../dicom-importer/components/work-session-library/work-session-library.component */ 88507); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); class LiveAnalysesPageComponent { static ɵfac = function LiveAnalysesPageComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LiveAnalysesPageComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineComponent"]({ type: LiveAnalysesPageComponent, selectors: [["lib-live-analyses-page"]], hostAttrs: [1, "dark", "flex", "h-full", "flex-col", "bg-surface-950", "text-color"], decls: 6, vars: 3, consts: [[1, "border-surface-800", "flex", "h-14", "shrink-0", "items-center", "gap-3", "border-b", "bg-(--p-app-chrome-page-header)", "px-5", "select-none"], [1, "font-semibold", "tracking-wide"], [1, "min-h-0", "flex-1"], [1, "block", "h-full"]], template: function LiveAnalysesPageComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](0, "header", 0)(1, "h1", 1); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](4, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelement"](5, "lib-work-session-library", 3); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipeBind1"](3, 1, "imagingLibrary.liveAnalysesTitle"), " "); } }, dependencies: [_ngx_translate_core__WEBPACK_IMPORTED_MODULE_0__.TranslateModule, _dicom_importer_components_work_session_library_work_session_library_component__WEBPACK_IMPORTED_MODULE_1__.WorkSessionLibraryComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_0__.TranslatePipe], encapsulation: 2 }); } /***/ }, /***/ 72754 /*!***************************************************************************!*\ !*** ./libs/feature/src/lib/interaction-mode/interaction-mode.service.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ InteractionModeService: () => (/* binding */ InteractionModeService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/store */ 15585); class InteractionModeService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.AnnotationFacade); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.ProtocolFacade); _interactionMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.linkedSignal)(() => { const annotation = this.annotationFacade.annotationBeingCreated(); if (annotation !== undefined) { return { annotation, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.CREATE }; } return { type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.SELECT }; }, ...(ngDevMode ? [{ debugName: "_interactionMode" }] : [])); get interactionMode() { return this._interactionMode; } annotationAddingPointsTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { let annotation; const interactionMode = this._interactionMode(); const annotations = this.annotationFacade.annotationMap(); if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.ADD_POINTS) { annotation = annotations[interactionMode.annotationId]; } return annotation; }, ...(ngDevMode ? [{ debugName: "annotationAddingPointsTo" }] : [])); startAddingPoints(annotationId) { this._interactionMode.set({ annotationId, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.ADD_POINTS }); } clearMode() { if (this._interactionMode().type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.SELECT) { this._interactionMode.set({ type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.InteractionModeType.SELECT }); } } static ɵfac = function InteractionModeService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InteractionModeService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: InteractionModeService, factory: InteractionModeService.ɵfac }); } /***/ }, /***/ 47136 /*!*********************************************************!*\ !*** ./libs/feature/src/lib/logging/logging.service.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LoggingService: () => (/* binding */ LoggingService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var consola__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! consola */ 84544); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); class LoggingService { log = (0,consola__WEBPACK_IMPORTED_MODULE_1__.createConsola)({ level: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.IS_DEV_BUILD) ? 4 : 2 }); constructor() { this.log.withTag('other').wrapAll(); } getChildLogger(tag) { return this.log.withTag(tag); } static ɵfac = function LoggingService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LoggingService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: LoggingService, factory: LoggingService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 14337 /*!***********************************************!*\ !*** ./libs/feature/src/lib/logging/utils.ts ***! \***********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getLogger: () => (/* binding */ getLogger) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _logging_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logging.service */ 47136); function getLogger(name) { (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.assertInInjectionContext)(getLogger); return (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_logging_service__WEBPACK_IMPORTED_MODULE_1__.LoggingService).getChildLogger(name); } /***/ }, /***/ 42948 /*!*****************************************************************************************!*\ !*** ./libs/feature/src/lib/oauth-feature-pages/auth-wrapper/auth-wrapper.component.ts ***! \*****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AuthWrapperComponent: () => (/* binding */ AuthWrapperComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 19305); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/router */ 38709); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = (a0, a1) => ({ clientVersion: a0, backendVersion: a1 }); function AuthWrapperComponent_Conditional_26_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p", 12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "a", 14); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](2, 2, "auth.already-have-account"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](5, 4, "auth.sign-in"), " "); } } function AuthWrapperComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p", 12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "a", 15); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](2, 2, "auth.no-account"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](5, 4, "auth.create-one"), " "); } } function AuthWrapperComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p", 13); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind2"](2, 1, "auth.login-form.version-info", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction2"](4, _c0, ctx_r0.clientVersion, ctx_r0.backendVersion())), " "); } } class AuthWrapperComponent { authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.AuthService); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_5__.Router); environment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.ENV); loading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(false, ...(ngDevMode ? [{ debugName: "loading" }] : [])); error = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "error" }] : [])); provider = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.Provider; clientVersion = this.environment.version ?? 'unknown'; backendVersion = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "backendVersion" }] : [])); constructor() { this.loadBackendVersion(); } currentUrl = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)(this.router.events.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_8__.filter)(event => event instanceof _angular_router__WEBPACK_IMPORTED_MODULE_5__.NavigationEnd), (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.map)(event => event.urlAfterRedirects)), { initialValue: this.router.url }); isSignUp = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.currentUrl().startsWith('/sign-up'), ...(ngDevMode ? [{ debugName: "isSignUp" }] : [])); continueWith(provider) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const api = globalThis.electronAPI; const authUrl = `${_this.environment.apiUrl}/oauth/${provider}`; if (api && typeof api.openOAuth === 'function') { _this.loading.set(true); try { const { accessToken, refreshToken } = yield api.openOAuth(authUrl); if (accessToken && refreshToken) { _this.authService.setOauthTokens(accessToken, refreshToken); yield (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.firstValueFrom)(_this.authService.fetchUser()); yield _this.router.navigate([_this.environment.loginRouteRedirect]); } } catch (error) { _this.error.set(error instanceof _angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpErrorResponse ? error.error?.error?.message : 'Login failed'); } finally { _this.loading.set(false); } } else { _this.authService.loginWith(provider); } })(); } loadBackendVersion() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const apiUrl = _this2.environment.apiUrl; if (!apiUrl || !(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.isValidBackendApiUrl)(apiUrl)) return; try { const response = yield fetch(`${(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.normalizeBackendApiUrl)(apiUrl)}/system/version`); if (!response.ok) return; const payload = yield response.json(); if (payload.version) _this2.backendVersion.set(payload.version); } catch { // Keep the unavailable fallback when the backend cannot be reached. } })(); } static ɵfac = function AuthWrapperComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AuthWrapperComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵdefineComponent"]({ type: AuthWrapperComponent, selectors: [["lib-auth-wrapper"]], decls: 29, vars: 20, consts: [[1, "bg-surface-950", "flex", "min-h-screen", "items-center", "justify-center"], [1, "animate-fade-in-up", "bg-surface-900", "w-full", "max-w-md", "rounded-2xl", "shadow-2xl"], [1, "p-8"], ["data-test-id", "auth-wrapper-div-logo", 1, "mb-4", "flex", "justify-center"], ["src", "assets/svg/logo.svg", "fill", "", "alt", "Logo", 1, "size-20"], [1, "text-color", "mb-4", "text-center", "text-xl", "font-bold"], [1, "text-md", "text-color", "mb-6", "text-center"], [1, "my-6", "flex", "items-center"], [1, "bg-surface-700", "h-px", "grow"], [1, "text-muted-color", "px-3", "text-sm"], [1, "space-y-2"], ["data-test-id", "auth-wrapper-button-google-sign-in", "type", "button", 1, "bg-surface-800", "text-surface-300", "hover:bg-surface-700", "flex", "w-full", "items-center", "justify-center", "rounded-lg", "border-0", "py-2", "transition", 3, "click"], [1, "text-muted-color", "mt-6", "text-center", "text-sm"], [1, "text-surface-500", "my-2", "text-center", "text-xs"], ["data-test-id", "auth-wrapper-a-sign-in", "routerLink", "/login", 1, "text-color", "underline"], ["data-test-id", "auth-wrapper-a-sign-up", "routerLink", "/sign-up", 1, "text-color", "underline"]], template: function AuthWrapperComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](4, "img", 4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](5, "h1", 5); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](9, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](11, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](13, "router-outlet"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](14, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](15, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](16, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](17); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](18, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](19, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](20, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](21, "div", 10)(22, "button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("click", function AuthWrapperComponent_Template_button_click_22_listener() { return ctx.continueWith(ctx.provider.GOOGLE); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](23); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](24, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](25, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](26, AuthWrapperComponent_Conditional_26_Template, 6, 6, "p", 12)(27, AuthWrapperComponent_Conditional_27_Template, 6, 6, "p", 12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](28, AuthWrapperComponent_Conditional_28_Template, 3, 7, "p", 13); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", ctx.isSignUp() ? _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](7, 6, "auth.welcome-message-new-user") : _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](8, 8, "auth.welcome-message-returning-user"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", ctx.isSignUp() ? _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](11, 10, "auth.welcome-subtitle-new-user") : _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](12, 12, "auth.welcome-subtitle-returning-user"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", ctx.isSignUp() ? _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](18, 14, "auth.sign-up-form.provider-sign-up-alternative-message") : _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](19, 16, "auth.login-form.provider-sign-in-alternative-message"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](24, 18, "auth.provider-sign-in.google"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx.isSignUp() ? 26 : 27); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](!ctx.isSignUp() ? 28 : -1); } }, dependencies: [_angular_router__WEBPACK_IMPORTED_MODULE_6__.RouterLink, _angular_router__WEBPACK_IMPORTED_MODULE_5__.RouterOutlet, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 40531 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/oauth-feature-pages/oauth-page.routes.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ oauthPageRoutes: () => (/* binding */ oauthPageRoutes) /* harmony export */ }); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _auth_wrapper_auth_wrapper_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./auth-wrapper/auth-wrapper.component */ 42948); const oauthPageRoutes = [{ canActivate: [_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_0__.authGuard, _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_0__.sessionCleanupGuard], children: [{ loadComponent: () => Promise.all(/*! import() */[__webpack_require__.e("common"), __webpack_require__.e("libs_feature_src_lib_oauth-feature-pages_login_login_component_ts")]).then(__webpack_require__.bind(__webpack_require__, /*! ./login/login.component */ 12578)).then(m => m.LoginComponent), path: 'login' }, { loadComponent: () => Promise.all(/*! import() */[__webpack_require__.e("common"), __webpack_require__.e("libs_feature_src_lib_oauth-feature-pages_sign-up_sign-up_component_ts")]).then(__webpack_require__.bind(__webpack_require__, /*! ./sign-up/sign-up.component */ 19026)).then(m => m.SignUpComponent), path: 'sign-up' }], component: _auth_wrapper_auth_wrapper_component__WEBPACK_IMPORTED_MODULE_1__.AuthWrapperComponent, path: '' }, { canActivate: [_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_0__.sessionCleanupGuard], loadComponent: () => __webpack_require__.e(/*! import() */ "libs_feature_src_lib_oauth-feature-pages_oauth-callback_oauth-callback_component_ts").then(__webpack_require__.bind(__webpack_require__, /*! ./oauth-callback/oauth-callback.component */ 11718)).then(m => m.OauthCallbackComponent), path: 'oauth-callback' }]; /***/ }, /***/ 76860 /*!*****************************************************************************************!*\ !*** ./libs/feature/src/lib/phase-selection-dialog/phase-selection-dialog.component.ts ***! \*****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PhaseSelectionDialogComponent: () => (/* binding */ PhaseSelectionDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ count: a0 }); function PhaseSelectionDialogComponent_ng_template_2_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind2"](2, 1, "phaseSelection.selectedCount", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](4, _c0, ctx_r1.selectedPhases().length)), " "); } } function PhaseSelectionDialogComponent_ng_template_2_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](0); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx_r1.columnLabel, " "); } } function PhaseSelectionDialogComponent_ng_template_2_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](2, 1, "multiphase.rWaveLabel")); } } function PhaseSelectionDialogComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "tr")(1, "th", 7); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](2, "p-tableHeaderCheckbox", 8); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](3, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](4, PhaseSelectionDialogComponent_ng_template_2_Conditional_4_Template, 3, 6, "span", 9)(5, PhaseSelectionDialogComponent_ng_template_2_Conditional_5_Template, 1, 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](6, PhaseSelectionDialogComponent_ng_template_2_Conditional_6_Template, 3, 3, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx_r1.selectedPhases().length > 0 ? 4 : 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx_r1.gated ? 6 : -1); } } function PhaseSelectionDialogComponent_ng_template_4_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "td", 13); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const phase_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](phase_r3.detail ?? "\u2014"); } } function PhaseSelectionDialogComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "tr", 10)(1, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](2, "p-tableCheckbox", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](3, "td")(4, "span", 12); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](6, PhaseSelectionDialogComponent_ng_template_4_Conditional_6_Template, 2, 1, "td", 13); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const phase_r3 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pSelectableRow", phase_r3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("value", phase_r3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](phase_r3.label); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx_r1.gated ? 6 : -1); } } class PhaseSelectionDialogComponent { dialogRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DynamicDialogRef); config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DynamicDialogConfig); phases = this.config.data?.phases ?? []; columnLabel = this.config.data?.columnLabel ?? ''; // Gated series carry an R-R value per phase → show the R-R column; non-gated volumes don't. gated = this.phases.some(phase => phase.detail !== undefined); // All phases selected initially; the header checkbox toggles them. selectedPhases = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([...this.phases], ...(ngDevMode ? [{ debugName: "selectedPhases" }] : [])); canConfirm() { return this.selectedPhases().length > 0; } confirm() { if (!this.canConfirm()) return; // Return ids in the original phase order, not selection order. const selectedIds = new Set(this.selectedPhases().map(phase => phase.id)); this.dialogRef.close(this.phases.filter(phase => selectedIds.has(phase.id)).map(p => p.id)); } cancel() { this.dialogRef.close(undefined); } static ɵfac = function PhaseSelectionDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PhaseSelectionDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: PhaseSelectionDialogComponent, selectors: [["lib-phase-selection-dialog"]], decls: 11, vars: 11, consts: [["header", ""], ["body", ""], [1, "flex", "flex-col", "gap-3"], ["dataKey", "id", "selectionMode", "multiple", "scrollHeight", "20rem", 3, "selectionChange", "value", "selection", "scrollable"], [1, "flex", "justify-end", "gap-2", "pt-2"], ["data-test-id", "phase-selection-dialog-p-button-cancel", "severity", "secondary", 3, "click", "outlined", "label"], ["data-test-id", "phase-selection-dialog-p-button-confirm", 3, "click", "label", "disabled"], [2, "width", "3rem"], ["data-test-id", "phase-selection-dialog-p-tableHeaderCheckbox-select-all"], [1, "text-primary-500"], [3, "pSelectableRow"], [3, "value"], [1, "text-sm", "font-medium"], [1, "text-muted-color", "text-sm"]], template: function PhaseSelectionDialogComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 2)(1, "p-table", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("selectionChange", function PhaseSelectionDialogComponent_Template_p_table_selectionChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx.selectedPhases, $event) || (ctx.selectedPhases = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplate"](2, PhaseSelectionDialogComponent_ng_template_2_Template, 7, 2, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplateRefExtractor"])(4, PhaseSelectionDialogComponent_ng_template_4_Template, 7, 4, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](6, "div", 4)(7, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function PhaseSelectionDialogComponent_Template_p_button_click_7_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx.cancel()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](9, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipe"](10, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("click", function PhaseSelectionDialogComponent_Template_p_button_click_9_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx.confirm()); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("value", ctx.phases); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("selection", ctx.selectedPhases); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("scrollable", true); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("outlined", true)("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](8, 7, "phaseSelection.cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpipeBind1"](10, 9, "phaseSelection.confirm"))("disabled", !ctx.canConfirm()); } }, dependencies: [_angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormsModule, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateModule, primeng_button__WEBPACK_IMPORTED_MODULE_3__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_3__.Button, primeng_table__WEBPACK_IMPORTED_MODULE_5__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_5__.Table, primeng_table__WEBPACK_IMPORTED_MODULE_5__.SelectableRow, primeng_table__WEBPACK_IMPORTED_MODULE_5__.TableCheckbox, primeng_table__WEBPACK_IMPORTED_MODULE_5__.TableHeaderCheckbox, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 3124 /*!***************************************************************************************!*\ !*** ./libs/feature/src/lib/phase-selection-dialog/phase-selection-dialog.service.ts ***! \***************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PhaseSelectionDialogService: () => (/* binding */ PhaseSelectionDialogService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _phase_selection_dialog_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./phase-selection-dialog.component */ 76860); class PhaseSelectionDialogService { dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DialogService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); database = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.DicomDatabaseService); // Metadata-only separation + prompt — runs before any volume loads. selectForSeries(studyUid, seriesUid, storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const { phases } = yield (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.separateSeriesPhases)(_this.database, studyUid, seriesUid, storeUid); return _this.selectFromPhases(phases); })(); } // Single-phase shows no dialog. selectFromPhases(phases) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (phases.length <= 1) { return phases.map(phase => phase.id); } const triggerUnit = _this2.translate.instant('multiphase.triggerUnit'); const items = phases.map(phase => ({ detail: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.formatPhaseIdentification)(phase.identification, { triggerUnit }), id: phase.id, label: phase.label })); // "Phase" only when the volumes carry cardiac timing (an R-R value was derived); else "Volume". const gated = items.some(item => item.detail !== undefined); const columnLabel = _this2.translate.instant(gated ? 'multiphase.phase' : 'multiphase.volume'); const dialogReference = _this2.dialogService.open(_phase_selection_dialog_component__WEBPACK_IMPORTED_MODULE_7__.PhaseSelectionDialogComponent, { data: { columnLabel, phases: items }, header: _this2.translate.instant('phaseSelection.header'), resizable: false, width: '32rem' }); if (!dialogReference) return undefined; const result = yield (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.firstValueFrom)(dialogReference.onClose); return result; })(); } static ɵfac = function PhaseSelectionDialogService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PhaseSelectionDialogService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: PhaseSelectionDialogService, factory: PhaseSelectionDialogService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 18194 /*!***********************************************************!*\ !*** ./libs/feature/src/lib/pipes/modality-label.pipe.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ModalityLabelPipe: () => (/* binding */ ModalityLabelPipe) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); class ModalityLabelPipe { translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); transform(value) { if (!value) { return this.translate.instant('modality.unknown'); } const key = `modality.${value.toLowerCase()}`; const translation = this.translate.instant(key); return translation === key ? value : translation; } static ɵfac = function ModalityLabelPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ModalityLabelPipe)(); }; static ɵpipe = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefinePipe"]({ name: "modalityLabel", type: ModalityLabelPipe, pure: true }); } /***/ }, /***/ 23093 /*!*************************************************************!*\ !*** ./libs/feature/src/lib/protocols/definitions/index.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEFAULT_PROTOCOLS: () => (/* binding */ DEFAULT_PROTOCOLS), /* harmony export */ RelativeTestProtocol: () => (/* reexport safe */ _relative_test_protocol__WEBPACK_IMPORTED_MODULE_0__.RelativeTestProtocol), /* harmony export */ TaviProtocol: () => (/* reexport safe */ _tavi_protocol__WEBPACK_IMPORTED_MODULE_1__.TaviProtocol) /* harmony export */ }); /* harmony import */ var _relative_test_protocol__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./relative-test.protocol */ 34682); /* harmony import */ var _tavi_protocol__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tavi.protocol */ 12541); const DEFAULT_PROTOCOLS = [_tavi_protocol__WEBPACK_IMPORTED_MODULE_1__.TaviProtocol]; /***/ }, /***/ 34682 /*!******************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/definitions/relative-test.protocol.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RelativeTestProtocol: () => (/* binding */ RelativeTestProtocol) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/ui */ 79048); // Figma-sourced colors, one per placeholder group. The picks are arbitrary, // this fixture only needs the groups to be visually distinct. const COLOR_AB = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['sinus-point']; const COLOR_CD = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.appColorTokens.amber['400']; const COLOR_ABCD = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.appColorTokens.blue['500']; const COLOR_EF = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.appColorTokens.neutral['400']; const COLOR_ABCDEF = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.appColorTokens.neutral['900']; const COLOR_OTHER = _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.appColorTokens.green['500']; // Define protocol/placeholder ids here for easy reference / clearer relationship definitions const PROTOCOL_ID_RELTEST = '3fd5bdbe-9810-40d8-ac49-084cd625b8a0'; const PLACEHOLDER_ID_POINT_A = '99d32d70-74da-449c-9b7d-5a530439a380'; const PLACEHOLDER_ID_POINT_B = 'cda3ffbe-5e96-4d2d-ae00-cf8096512474'; const PLACEHOLDER_ID_AB_DISTANCE = '4a87118a-1f28-4c78-8ca4-15e71c827e94'; const PLACEHOLDER_ID_POINT_C = '802d04c2-9738-4f6a-b814-1b4225495737'; const PLACEHOLDER_ID_POINT_D = '29783463-df18-481c-95b6-6e5bce9d87b2'; const PLACEHOLDER_ID_CD_DISTANCE = '29562f4d-0c54-475e-9e88-91f8fad9ca1f'; const PLACEHOLDER_ID_ABCD_DISTANCE = '6f53af52-08c4-407c-afce-fb3f9086e66f'; const PLACEHOLDER_ID_POINT_E = '9f36fd39-18b7-47a6-acd3-b853a472fefe'; const PLACEHOLDER_ID_POINT_F = '5130ce4b-b654-4dd3-801b-6f55f7642e4c'; const PLACEHOLDER_ID_EF_DISTANCE = '8b848d8a-469a-45aa-8fd0-fe0508b41138'; const PLACEHOLDER_ID_ABCDEF_DISTANCE = 'c5299064-c1b7-4390-aefe-de1a0bfcca54'; const CLOSEST_DISTANCE = 'closest-distance-between-annotations'; // Not to be used in production - just for testing that relative measurements populate as expected const RelativeTestProtocol = { id: PROTOCOL_ID_RELTEST, name: 'Relative Measurements Test', placeholders: [(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_AB, id: PLACEHOLDER_ID_POINT_A, name: 'Point A' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_OTHER, name: 'OTHER' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_AB, id: PLACEHOLDER_ID_POINT_B, name: 'Point B' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_OTHER, name: 'OTHER2' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: COLOR_AB, id: PLACEHOLDER_ID_AB_DISTANCE, name: 'A-B Distance', relationship: { sourceIds: [PLACEHOLDER_ID_POINT_A, PLACEHOLDER_ID_POINT_B], type: CLOSEST_DISTANCE } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_CD, id: PLACEHOLDER_ID_POINT_C, name: 'Point C' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_CD, id: PLACEHOLDER_ID_POINT_D, name: 'Point D' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: COLOR_CD, id: PLACEHOLDER_ID_CD_DISTANCE, name: 'C-D Distance', relationship: { sourceIds: [PLACEHOLDER_ID_POINT_C, PLACEHOLDER_ID_POINT_D], type: CLOSEST_DISTANCE } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: COLOR_ABCD, id: PLACEHOLDER_ID_ABCD_DISTANCE, name: 'AB-CD Distance', relationship: { sourceIds: [PLACEHOLDER_ID_AB_DISTANCE, PLACEHOLDER_ID_CD_DISTANCE], type: CLOSEST_DISTANCE } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_EF, id: PLACEHOLDER_ID_POINT_E, name: 'Point E' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: COLOR_EF, id: PLACEHOLDER_ID_POINT_F, name: 'Point F' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: COLOR_EF, id: PLACEHOLDER_ID_EF_DISTANCE, name: 'E-F Distance', relationship: { sourceIds: [PLACEHOLDER_ID_POINT_E, PLACEHOLDER_ID_POINT_F], type: CLOSEST_DISTANCE } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: COLOR_ABCDEF, id: PLACEHOLDER_ID_ABCDEF_DISTANCE, name: 'ABCD-EF Distance', relationship: { sourceIds: [PLACEHOLDER_ID_ABCD_DISTANCE, PLACEHOLDER_ID_EF_DISTANCE], type: CLOSEST_DISTANCE } })] }; /***/ }, /***/ 12541 /*!*********************************************************************!*\ !*** ./libs/feature/src/lib/protocols/definitions/tavi.protocol.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TaviProtocol: () => (/* binding */ TaviProtocol) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/ui */ 79048); // Define protocol/placeholder ids here for easy reference / clearer relationship definitions const PROTOCOL_ID_TAVI = _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.TAVI_PROTOCOL_ID; const PLACEHOLDER_ID_AV_ANNULUS = '23967a10-9b37-4467-895a-1b678cca6dc2'; const PLACEHOLDER_ID_LCC_NADIR = 'c1c0f1e3-fc4c-4b17-b6b8-c6501834ff19'; const PLACEHOLDER_ID_RCC_NADIR = '35a56ca9-c484-433c-973e-24409cb975d7'; const PLACEHOLDER_ID_NCC_NADIR = '00b786f7-f8ec-43a8-bbbb-90deb1ce4bb6'; const PLACEHOLDER_ID_SOV_CONTOUR = '5b0c20c7-94ee-4ea8-ab7b-b9952c85e8dd'; const PLACEHOLDER_ID_COMMISSURE_1 = 'baee0a2c-e0b7-5202-b0d5-d7583ead10f5'; const PLACEHOLDER_ID_COMMISSURE_2 = '9a279730-05ca-59f2-a861-3c155d8f88be'; const PLACEHOLDER_ID_COMMISSURE_3 = 'f6d09d1a-ca66-5e28-8da0-3bf8a24902fe'; const PLACEHOLDER_ID_SINUS_1 = 'dbc9f17a-93e4-559b-a25d-e602ab3c98f9'; const PLACEHOLDER_ID_SINUS_2 = '613f9d24-efdc-5fbd-bd7e-c335d2ba1a76'; const PLACEHOLDER_ID_SINUS_3 = 'ca687a0d-908b-5211-b76e-c2d0e7e95e58'; const PLACEHOLDER_ID_LEFT_CORONARY_HEIGHT = '8dc0516e-0d3a-53d8-8923-a96e7ec8f9a6'; const PLACEHOLDER_ID_RIGHT_CORONARY_HEIGHT = '45c3d9d0-c234-5bb0-97a1-bed2d8c79ac3'; const PLACEHOLDER_ID_SINOTUBULAR_JUNCTION = '64889f29-e86f-46db-acdd-2cb252d2a18b'; const PLACEHOLDER_ID_LVOT_CONTOUR = '724af5bf-e4ca-508e-84eb-f7f797b4ffef'; const ATTACHED_POINT = 'attached-point'; const TaviProtocol = { form: { // Unless proceed is true + the form is valid, we can't proceed with the rest canProceedRule: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('proceed', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(true)), fields: [{ key: 'variant', options: [{ value: 'tricuspid' }, { value: 'tricommissural-functional-bicuspid' }, { value: 'bav-type-0' }, { value: 'bav-type-1-rl' }, { value: 'bav-type-1-ln' }, { value: 'bav-type-1-rn' }, { value: 'bav-type-2' }, { value: 'unicuspid' }, { value: 'tav-balloon-expandable' }, { value: 'tav-self-expanding' }, { value: 'sav-tissue' }, { value: 'sav-metallic' }, { value: 'undetermined' }], representation: 'select', valueType: 'text' }, { key: 'artifacts', options: [{ exclusive: true, value: 'none' }, { value: 'calcium-blooming' }, { value: 'contrast-related-streaks' }, { value: 'metal-related-streaks' }, { value: 'high-noise-level' }, { value: 'poor-contrast-opacification' }, { value: 'banding-stitching' }], representation: 'checkboxes', valueType: 'multi-text' }, { key: 'imageQuality', options: [{ value: 'good' }, { value: 'fair' }, { value: 'poor' }], representation: 'select', valueType: 'text' }, { key: 'proceed', representation: 'radio', valueType: 'boolean' }, { key: 'proceedReason', options: [{ value: 'n1' }, { value: 'n2' }, { value: 'n3' }, { value: 'n4' }, { value: 'n5' }], representation: 'select', valueType: 'text', visibleWhen: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('proceed', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(false)) }, { key: 'comments', representation: 'textarea', valueType: 'text' }], name: 'Classification and quality', required: true, validation: { artifacts: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)(), // Comments must be added when the other reason is selected comments: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.iff)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.and)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('proceed', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(false)), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('proceedReason', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)('n5'))), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)('protocolDef.tavi.form.error.notProceeding')), imageQuality: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)(), proceed: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.and)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)(), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.iff)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('imageQuality', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)('poor')), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(false, 'protocolDef.tavi.form.error.poorImageQuality')), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.iff)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('variant', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.oneOf)(['tricuspid', 'tricommissural-functional-bicuspid', 'bav-type-1-rl', 'bav-type-1-ln', 'bav-type-1-rn'])), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)(), // If one of the above is selected, can still be skipped for other reasons (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(false, 'protocolDef.tavi.form.error.cannotProceedWithSelectedVariant'))), proceedReason: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.iff)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.forField)('proceed', (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.equals)(false)), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)()), variant: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)(), volumeIdentifier: (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.required)() } }, id: PROTOCOL_ID_TAVI, name: 'TAVI/TAVR', placeholders: [(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.annulus, id: PLACEHOLDER_ID_AV_ANNULUS, name: 'Aortic valve annulus' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['nadir-lcc'], id: PLACEHOLDER_ID_LCC_NADIR, name: 'LCC nadir', relationship: { sourceIds: [PLACEHOLDER_ID_AV_ANNULUS], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['nadir-rcc'], id: PLACEHOLDER_ID_RCC_NADIR, name: 'RCC nadir', relationship: { sourceIds: [PLACEHOLDER_ID_AV_ANNULUS], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['nadir-ncc'], id: PLACEHOLDER_ID_NCC_NADIR, name: 'NCC nadir', relationship: { sourceIds: [PLACEHOLDER_ID_AV_ANNULUS], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['coronary-height-left'], id: PLACEHOLDER_ID_LEFT_CORONARY_HEIGHT, name: 'Left coronary height', relationship: { sourceIds: [PLACEHOLDER_ID_AV_ANNULUS], type: 'projected-distance' } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['coronary-height-right'], id: PLACEHOLDER_ID_RIGHT_CORONARY_HEIGHT, name: 'Right coronary height', relationship: { sourceIds: [PLACEHOLDER_ID_AV_ANNULUS], type: 'projected-distance' } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.sov, id: PLACEHOLDER_ID_SOV_CONTOUR, name: 'SoV contour' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.commissure, id: PLACEHOLDER_ID_COMMISSURE_1, name: 'Commissure 1', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.commissure, id: PLACEHOLDER_ID_COMMISSURE_2, name: 'Commissure 2', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.commissure, id: PLACEHOLDER_ID_COMMISSURE_3, name: 'Commissure 3', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['sinus-point'], id: PLACEHOLDER_ID_SINUS_1, name: 'Sinus 1', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['sinus-point'], id: PLACEHOLDER_ID_SINUS_2, name: 'Sinus 2', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors['sinus-point'], id: PLACEHOLDER_ID_SINUS_3, name: 'Sinus 3', relationship: { sourceIds: [PLACEHOLDER_ID_SOV_CONTOUR], type: ATTACHED_POINT } }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.stj, id: PLACEHOLDER_ID_SINOTUBULAR_JUNCTION, name: 'STJ contour' }), (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.placeholder)({ annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE, color: _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.annotationHexColors.lvot, id: PLACEHOLDER_ID_LVOT_CONTOUR, name: 'LVOT contour' })] }; /***/ }, /***/ 61632 /*!*************************************************!*\ !*** ./libs/feature/src/lib/protocols/index.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEFAULT_PROTOCOLS: () => (/* reexport safe */ _definitions__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_PROTOCOLS), /* harmony export */ PlaceholderCardComponent: () => (/* reexport safe */ _placeholder_card_placeholder_card_component__WEBPACK_IMPORTED_MODULE_1__.PlaceholderCardComponent), /* harmony export */ ProtocolCreationService: () => (/* reexport safe */ _protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_2__.ProtocolCreationService), /* harmony export */ RelativeTestProtocol: () => (/* reexport safe */ _definitions__WEBPACK_IMPORTED_MODULE_0__.RelativeTestProtocol), /* harmony export */ TaviProtocol: () => (/* reexport safe */ _definitions__WEBPACK_IMPORTED_MODULE_0__.TaviProtocol) /* harmony export */ }); /* harmony import */ var _definitions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./definitions */ 23093); /* harmony import */ var _placeholder_card_placeholder_card_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./placeholder-card/placeholder-card.component */ 37076); /* harmony import */ var _protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./protocol-creation-service/protocol-creation.service */ 88304); /***/ }, /***/ 37076 /*!***************************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/placeholder-card/placeholder-card.component.ts ***! \***************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PlaceholderCardComponent: () => (/* binding */ PlaceholderCardComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../card-theme/card-theme */ 92147); /* harmony import */ var _protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../protocol-creation-service/protocol-creation.service */ 88304); const _c0 = ["nameLabel"]; const _c1 = () => ({ color: "var(--p-accordion-header-toggle-icon-color)" }); const _c2 = a0 => ({ secondary: a0 }); const _c3 = a0 => ({ outlined: a0 }); function PlaceholderCardComponent_ng_container_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementContainer"](0); } } function PlaceholderCardComponent_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "span", 13); } } function PlaceholderCardComponent_ng_container_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementContainer"](0); } } function PlaceholderCardComponent_ng_container_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementContainer"](0); } } function PlaceholderCardComponent_ng_template_11_ng_container_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementContainer"](0); } } function PlaceholderCardComponent_ng_template_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 14)(1, "span", 15, 6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](4, PlaceholderCardComponent_ng_template_11_ng_container_4_Template, 1, 0, "ng-container", 10); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const createBtn_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreference"](16); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("pTooltip", ctx_r0.isNameClamped() ? ctx_r0.placeholder().name : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", ctx_r0.placeholder().name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("ngTemplateOutlet", createBtn_r2); } } function PlaceholderCardComponent_ng_template_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](1, "lib-icon", 16); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵclassMap"](ctx_r0.cn("flex size-7.5 shrink-0 items-center justify-center rounded-full", ctx_r0.active() ? "bg-surface-900" : "bg-surface-800")); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleProp"]("color", ctx_r0.placeholder().color); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("icon", ctx_r0.placeholder().annotationType); } } function PlaceholderCardComponent_ng_template_15_Conditional_0_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "lib-icon", 20); } } function PlaceholderCardComponent_ng_template_15_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("click", function PlaceholderCardComponent_ng_template_15_Conditional_0_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r0.onCreateClick()); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](2, PlaceholderCardComponent_ng_template_15_Conditional_0_ng_template_2_Template, 1, 0, "ng-template", null, 7, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpureFunction1"](7, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpureFunction1"](5, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpureFunction0"](4, _c1))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](1, 2, "protocols.createAnnotation")); } } function PlaceholderCardComponent_ng_template_15_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "span", 18); } } function PlaceholderCardComponent_ng_template_15_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](0, PlaceholderCardComponent_ng_template_15_Conditional_0_Template, 4, 9, "p-button", 17)(1, PlaceholderCardComponent_ng_template_15_Conditional_1_Template, 1, 0, "span", 18); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx_r0.showCreateButton() ? 0 : 1); } } function PlaceholderCardComponent_ng_template_17_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "div", 21); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleProp"]("background-color", ctx_r0.active() ? ctx_r0.placeholder().color : ""); } } const TOKEN_SURFACE_200 = '{surface.200}'; const TOKEN_SURFACE_300 = '{surface.300}'; const TOKEN_SURFACE_500 = '{surface.500}'; const DARK_CARD_THEME = { active: { bg: '{surface.800}', hover: TOKEN_SURFACE_200, icon: TOKEN_SURFACE_500, text: '{surface.100}' }, default: { bg: '{app.surface.card}', hover: TOKEN_SURFACE_300, icon: TOKEN_SURFACE_500, text: '{surface.500}' }, disabled: { bg: '{app.surface.card}', hover: TOKEN_SURFACE_500, icon: TOKEN_SURFACE_500, text: TOKEN_SURFACE_500 } }; class PlaceholderCardComponent { placeholder = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "placeholder" }] : [])); annotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(...(ngDevMode ? [undefined, { debugName: "annotation" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); active = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "active" }] : [])); disabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "disabled" }] : [])); host = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.ElementRef); protocolCreation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_14__.ProtocolCreationService); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.ProtocolFacade); nameLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild)('nameLabel', ...(ngDevMode ? [{ debugName: "nameLabel" }] : [])); isNameClamped = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(false, ...(ngDevMode ? [{ debugName: "isNameClamped" }] : [])); filled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => !!this.annotation(), ...(ngDevMode ? [{ debugName: "filled" }] : [])); showCreateButton = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const active = this.active(); const disabled = this.disabled(); const filled = this.filled(); const placeholder = this.placeholder(); const { instance } = this.protocolFacade.activeProtocol(); return !active && !disabled && !filled && !(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_9__.canPlaceholderBeAutocreated)(placeholder) && instance && (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_9__.canPlaceholderBeCompleted)(placeholder, instance); }, ...(ngDevMode ? [{ debugName: "showCreateButton" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.afterEveryRender)(() => { const element = this.nameLabel()?.nativeElement; if (!element) return; const clamped = element.scrollHeight > element.clientHeight; if (clamped !== this.isNameClamped()) this.isNameClamped.set(clamped); }); } mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const pt = this.pt(); const state = this.cardState(); const hoverClass = ['active', 'disabled'].includes(state) ? '' : _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_13__.CARD_HOVER_CLASS; return { ...pt, header: { ...pt?.header, root: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.cn)('flex-row gap-3 rounded-none pr-1 justify-start', hoverClass, pt?.header?.root), toggleicon: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.cn)('toggle-icon', pt?.header?.toggleicon) }, panel: { ...pt?.panel, root: { class: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.cn)('py-0 flex w-full border-none', hoverClass, pt?.panel?.root, state === 'disabled' && 'pointer-events-none'), style: { backgroundColor: 'var(--p-accordion-header-background)' } } } }; }, ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_13__.buildCardDt)(DARK_CARD_THEME[this.cardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_13__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.cn; cardState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const isActive = this.active(); const isDisabled = this.disabled(); if (isDisabled) return 'disabled'; if (isActive) return 'active'; return 'default'; }, ...(ngDevMode ? [{ debugName: "cardState" }] : [])); onCreateClick() { this.protocolCreation.start(this.placeholder()); } scrollTo() { this.host.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); } static ɵfac = function PlaceholderCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PlaceholderCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: PlaceholderCardComponent, selectors: [["lib-placeholder-card"]], viewQuery: function PlaceholderCardComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵviewQuerySignal"](ctx.nameLabel, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵqueryAdvance"](); } }, inputs: { placeholder: [1, "placeholder"], annotation: [1, "annotation"], pt: [1, "pt"], active: [1, "active"], disabled: [1, "disabled"] }, decls: 19, vars: 11, consts: [["panel", ""], ["toggleicon", ""], ["headerTitle", ""], ["cardIcon", ""], ["createBtn", ""], ["accentBar", ""], ["nameLabel", ""], ["icon", ""], [1, "grow", 3, "pt", "dt", "value"], [3, "pt"], [4, "ngTemplateOutlet"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-3", "py-0.5"], [1, "ml-2.5", "size-3"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], [1, "line-clamp-2", "wrap-anywhere", 3, "pTooltip"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"], ["data-test-id", "placeholder-card-p-button-create-annotation", "severity", "secondary", "outlined", "", "size", "small", 3, "dt", "pTooltip"], [1, "size-4", "h-[34px]"], ["data-test-id", "placeholder-card-p-button-create-annotation", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "dt", "pTooltip"], ["icon", "plus", 1, "text-surface-200", "size-(--p-app-icon-size-xs)"], [1, "absolute", "top-0", "left-0", "h-full", "w-1"]], template: function PlaceholderCardComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div")(1, "p-accordion-panel", 8, 0)(3, "p-accordion-header", 9); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](4, PlaceholderCardComponent_ng_container_4_Template, 1, 0, "ng-container", 10)(5, PlaceholderCardComponent_ng_template_5_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](7, "div", 11)(8, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](9, PlaceholderCardComponent_ng_container_9_Template, 1, 0, "ng-container", 10)(10, PlaceholderCardComponent_ng_container_10_Template, 1, 0, "ng-container", 10); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](11, PlaceholderCardComponent_ng_template_11_Template, 5, 3, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"])(13, PlaceholderCardComponent_ng_template_13_Template, 2, 5, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"])(15, PlaceholderCardComponent_ng_template_15_Template, 2, 1, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"])(17, PlaceholderCardComponent_ng_template_17_Template, 1, 2, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const headerTitle_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreference"](12); const cardIcon_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreference"](14); const accentBar_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreference"](18); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵclassMap"](ctx.cn("group border-surface-800 flex w-full overflow-hidden border-b", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", ctx.placeholder().id); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("ngTemplateOutlet", headerTitle_r4); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_6__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_6__.AccordionPanel, primeng_button__WEBPACK_IMPORTED_MODULE_7__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.IconComponent, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet, primeng_tooltip__WEBPACK_IMPORTED_MODULE_8__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 88304 /*!***********************************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/protocol-creation-service/protocol-creation.service.ts ***! \***********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolCreationService: () => (/* binding */ ProtocolCreationService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../logging/utils */ 14337); /* harmony import */ var _protocol_form_dialog_protocol_form_dialog_component__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../protocol-form-dialog/protocol-form-dialog.component */ 62472); class ProtocolCreationService { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_8__.getLogger)(ProtocolCreationService.name); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.AnnotationFacade); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.ProtocolFacade); dialog = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DialogService); activeProtocolForm = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { definition } = this.protocolFacade.activeProtocol(); return definition?.form; }, ...(ngDevMode ? [{ debugName: "activeProtocolForm" }] : [])); _activePlaceholder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "_activePlaceholder" }] : [])); activePlaceholder = this._activePlaceholder.asReadonly(); activePlaceholderFilled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const placeholder = this.activePlaceholder(); const { instance } = this.protocolFacade.activeProtocol(); return placeholder && instance?.placeholderMappings[placeholder.id] !== undefined; }, ...(ngDevMode ? [{ debugName: "activePlaceholderFilled" }] : [])); _creationSub = this.annotationFacade.creations$.subscribe(([createdId]) => { const placeholder = this.activePlaceholder(); const { definition, instance } = this.protocolFacade.activeProtocol(); if (placeholder && definition && instance && createdId) { this.protocolFacade.fillPlaceholder(definition.id, placeholder.id, createdId); } }); isEmpty = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition || !instance) { return true; } return Object.keys(instance.placeholderMappings).length === 0; }, ...(ngDevMode ? [{ debugName: "isEmpty" }] : [])); isBeingCreated = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.activePlaceholder() !== undefined, ...(ngDevMode ? [{ debugName: "isBeingCreated" }] : [])); progress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition || !instance) { return; } return { current: Object.keys(instance.placeholderMappings).length + 1, total: definition.placeholders.length }; }, ...(ngDevMode ? [{ debugName: "progress" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => { this._creationSub.unsubscribe(); }); } tryCreatingAnnotation(placeholder, instance) { if (!placeholder || !instance) { return; } const annotation = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.createAnnotationFromPlaceholder)(placeholder, instance); if (annotation) { if (!(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canPlaceholderBeCompleted)(placeholder, instance)) { this.goToNextPlaceholder(); } else if ((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canPlaceholderBeAutocreated)(placeholder)) { const annotationMap = this.annotationFacade.annotationMap(); const sources = placeholder.relationship?.sourceIds.map(placeholderId => { const annotationId = instance.placeholderMappings[placeholderId]; if (!annotationId) { return; } return annotationMap[annotationId]; }).filter(annotation => annotation !== undefined) ?? []; this.annotationFacade.addAnnotations((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__.updateRelativeMeasurement)(annotation, sources)); } else { this.annotationFacade.creatingAnnotation(annotation); } } } /** * Start the Protocol creation process, optionally at a specified placeholder. * Only works if there is an active protocol and the placeholder is part of it. */ start(placeholder) { const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition) { return; } const form = this.activeProtocolForm(); if (form && !(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canProceedFromProtocolForm)(form, instance?.formValues)) { this.handleProtocolFormInFlow(); return; } // Ensure provided placeholder is part of active protocol if (placeholder && !definition.placeholders.some(({ id }) => id === placeholder.id)) { this.log.warn('Placeholder received for different protocol'); return; } const startingPlaceholder = placeholder ?? (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getNextPlaceholder)(definition, instance); if (startingPlaceholder) { this._activePlaceholder.set(startingPlaceholder); } this.handleRelativePlaceholders(); } stop() { this._activePlaceholder.set(undefined); } cancelCurrentStep() { const placeholder = this.activePlaceholder(); const { instance } = this.protocolFacade.activeProtocol(); if (!instance || !placeholder) { return false; } // Cancel any in-progress annotations this.annotationFacade.cancelAnnotationCreation(); // If this placeholder already has an annotation, delete it if (this.activePlaceholderFilled()) { const toDelete = instance.placeholderMappings[placeholder.id]; if (toDelete) { this.annotationFacade.deleteAnnotations([toDelete]); } } // Unset the current placeholder this._activePlaceholder.set(undefined); return true; } restartCurrentStep() { const placeholder = this.activePlaceholder(); const { instance } = this.protocolFacade.activeProtocol(); if (!instance || !placeholder) { return; } // If this placeholder already has an annotation, delete it if (this.activePlaceholderFilled()) { const toDelete = instance.placeholderMappings[placeholder.id]; if (toDelete) { this.annotationFacade.deleteAnnotations([toDelete]); } } } undo() { console.log('undo()'); const placeholder = this.activePlaceholder(); const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition || !instance || !placeholder) { return; } const previous = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getPreviousPlaceholder)(definition, instance, placeholder.id); if (previous) { console.log('undo to', previous); const annotationId = instance.placeholderMappings[previous.id]; if (annotationId !== undefined) { this.annotationFacade.deleteAnnotations([annotationId]); } this._activePlaceholder.set(previous); } } clear() { const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition || !instance) { return; } const toDeleteIds = Object.values(instance.placeholderMappings); if (toDeleteIds.length > 0) { this.annotationFacade.deleteAnnotations(toDeleteIds); } this.protocolFacade.clearFormValues(instance.protocolId); } goToNextPlaceholder() { this._activePlaceholder.update(previous => { const { definition, instance } = this.protocolFacade.activeProtocol(); if (!definition || !instance) { return; } return (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getNextPlaceholder)(definition, instance, { afterPlaceholderId: previous?.id, loopBack: true, prioritizeAutoCreate: true }); }); this.handleRelativePlaceholders(); } handleCurrentPlaceholder() { const placeholder = this._activePlaceholder(); if (placeholder) { const { instance } = this.protocolFacade.activeProtocol(); this.tryCreatingAnnotation(placeholder, instance); } } openProtocolForm() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const formDefinition = _this.activeProtocolForm(); if (formDefinition === undefined) { return false; } const dialog = _this.dialog.open(_protocol_form_dialog_protocol_form_dialog_component__WEBPACK_IMPORTED_MODULE_9__.ProtocolFormDialog, { closeOnEscape: true, header: formDefinition.name, modal: true, pt: { content: { style: { display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' } } }, styleClass: 'max-h-9/10', width: '600px' }); if (dialog) { return !!(yield (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.firstValueFrom)(dialog.onClose)); } return false; })(); } handleProtocolFormInFlow() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const saved = yield _this2.openProtocolForm(); if (saved) { const form = _this2.activeProtocolForm(); const { instance } = _this2.protocolFacade.activeProtocol(); if (instance && form && (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canProceedFromProtocolForm)(form, instance?.formValues)) { _this2.goToNextPlaceholder(); } } })(); } handleRelativePlaceholders() { const placeholder = this._activePlaceholder(); const { instance } = this.protocolFacade.activeProtocol(); if (instance === undefined || placeholder === undefined) { return; } if ((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canPlaceholderBeAutocreated)(placeholder) && (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.canPlaceholderBeCompleted)(placeholder, instance)) { const annotation = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.createAnnotationFromPlaceholder)(placeholder, instance); if (annotation === undefined) { return; } const annotationMap = this.annotationFacade.annotationMap(); const sources = placeholder.relationship?.sourceIds.map(placeholderId => { const annotationId = instance.placeholderMappings[placeholderId]; if (!annotationId) { return; } return annotationMap[annotationId]; }).filter(annotation => annotation !== undefined) ?? []; this.annotationFacade.addAnnotations((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__.updateRelativeMeasurement)(annotation, sources)); this.goToNextPlaceholder(); } } static ɵfac = function ProtocolCreationService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolCreationService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: ProtocolCreationService, factory: ProtocolCreationService.ɵfac }); } /***/ }, /***/ 47716 /*!*******************************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/protocol-form-card/protocol-form-card.component.ts ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolFormCardComponent: () => (/* binding */ ProtocolFormCardComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../card-theme/card-theme */ 92147); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 14975); function ProtocolFormCardComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](0, "span", 10); } } function ProtocolFormCardComponent_ng_container_8_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementContainer"](0); } } function ProtocolFormCardComponent_ng_container_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementContainer"](0); } } function ProtocolFormCardComponent_ng_template_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div", 11)(1, "span", 12, 4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r0.formDefinition().name, " "); } } function ProtocolFormCardComponent_ng_template_12_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](1, "lib-icon", 13); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵclassMap"](ctx_r0.cn("flex size-7.5 shrink-0 items-center justify-center rounded-full", ctx_r0.complete() ? "bg-surface-900" : "bg-surface-800")); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("icon", ctx_r0.icon()); } } const DARK_CARD_THEME = { blocked: { bg: '{app.surface.card}', hover: '{surface.300}', icon: '{surface.500}', text: '{amber.500}' }, complete: { bg: '{app.surface.card}', hover: '{surface.300}', icon: '{surface.500}', text: '{surface.100}' }, default: { bg: '{app.surface.card}', hover: '{surface.300}', icon: '{surface.500}', text: '{surface.500}' }, invalid: { bg: '{app.surface.card}', hover: '{surface.300}', icon: '{surface.500}', text: '{red.500}' } }; class ProtocolFormCardComponent { formDefinition = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "formDefinition" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); blocked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "blocked" }] : [])); complete = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "complete" }] : [])); invalid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "invalid" }] : [])); mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const pt = this.pt(); const hoverClass = ''; return { ...pt, header: { ...pt?.header, root: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cn)('flex-row gap-3 rounded-none pr-1 justify-start', hoverClass, pt?.header?.root), toggleicon: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cn)('toggle-icon', pt?.header?.toggleicon) }, panel: { ...pt?.panel, root: { class: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cn)('py-0 flex w-full border-none', hoverClass, pt?.panel?.root), style: { backgroundColor: 'var(--p-accordion-header-background)' } } } }; }, ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_6__.buildCardDt)(DARK_CARD_THEME[this.cardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_6__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cn; cardState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const blocked = this.blocked(); const complete = this.complete(); const invalid = this.invalid(); if (blocked) { return 'blocked'; } if (invalid) { return 'invalid'; } if (complete) { return 'complete'; } return 'default'; }, ...(ngDevMode ? [{ debugName: "cardState" }] : [])); icon = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const cardState = this.cardState(); return CARD_STATE_ICONS[cardState]; }, ...(ngDevMode ? [{ debugName: "icon" }] : [])); static ɵfac = function ProtocolFormCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolFormCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineComponent"]({ type: ProtocolFormCardComponent, selectors: [["lib-protocol-form-card"]], inputs: { formDefinition: [1, "formDefinition"], pt: [1, "pt"], blocked: [1, "blocked"], complete: [1, "complete"], invalid: [1, "invalid"] }, decls: 14, vars: 10, consts: [["panel", ""], ["toggleicon", ""], ["headerTitle", ""], ["cardIcon", ""], ["nameLabel", ""], [1, "grow", 3, "pt", "dt", "value"], [3, "pt"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-3", "py-0.5"], [4, "ngTemplateOutlet"], [1, "ml-2.5", "size-3"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], [1, "line-clamp-2", "wrap-anywhere"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"]], template: function ProtocolFormCardComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div")(1, "p-accordion-panel", 5, 0)(3, "p-accordion-header", 6); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](4, ProtocolFormCardComponent_ng_template_4_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](6, "div", 7)(7, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](8, ProtocolFormCardComponent_ng_container_8_Template, 1, 0, "ng-container", 9)(9, ProtocolFormCardComponent_ng_container_9_Template, 1, 0, "ng-container", 9); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](10, ProtocolFormCardComponent_ng_template_10_Template, 4, 1, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplateRefExtractor"])(12, ProtocolFormCardComponent_ng_template_12_Template, 2, 3, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const headerTitle_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵreference"](11); const cardIcon_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵreference"](13); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵclassMap"](ctx.cn("group border-surface-800 flex w-full overflow-hidden border-b", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", "form"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r3); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("ngTemplateOutlet", headerTitle_r2); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_3__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_3__.AccordionPanel, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_4__.IconComponent, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet], encapsulation: 2, changeDetection: 0 }); } const CARD_STATE_ICONS = { blocked: 'ban', complete: 'check', default: 'clipboard', invalid: 'times' }; /***/ }, /***/ 62472 /*!***********************************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/protocol-form-dialog/protocol-form-dialog.component.ts ***! \***********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolFormDialog: () => (/* binding */ ProtocolFormDialog) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _protocol_form_protocol_form_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../protocol-form/protocol-form.component */ 51430); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["form"]; function ProtocolFormDialog_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](0, "lib-protocol-form", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](2, "div", 3)(3, "p-button", 4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ProtocolFormDialog_Conditional_1_Template_p_button_click_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.cancel()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](5, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ProtocolFormDialog_Conditional_1_Template_p_button_click_5_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.save()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("formDefinition", ctx)("formValues", ctx_r1.formValues()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipeBind1"](4, 4, "common.cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipeBind1"](6, 6, "common.save")); } } class ProtocolFormDialog { dialogReference = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__.DynamicDialogRef); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.ProtocolFacade); form = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('form'); formDefinition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.protocolFacade.activeProtocol().definition?.form, ...(ngDevMode ? [{ debugName: "formDefinition" }] : [])); formValues = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.protocolFacade.activeProtocol().instance?.formValues ?? {}, ...(ngDevMode ? [{ debugName: "formValues" }] : [])); cancel() { this.dialogReference.close(false); } save() { this.form().save(); this.dialogReference.close(true); } static ɵfac = function ProtocolFormDialog_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolFormDialog)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵdefineComponent"]({ type: ProtocolFormDialog, selectors: [["lib-protocol-form-dialog"]], viewQuery: function ProtocolFormDialog_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵviewQuerySignal"](ctx.form, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵqueryAdvance"](); } }, hostAttrs: [1, "flex", "flex-col", "min-h-0", "overflow-y-auto"], decls: 2, vars: 1, consts: [["form", ""], [1, "flex", "min-h-0", "flex-1", "flex-col", "gap-4"], [1, "flex", "min-h-0", "flex-col", "overflow-y-auto", 3, "formDefinition", "formValues"], [1, "flex", "justify-end", "gap-2"], ["severity", "secondary", "variant", "text", "data-test-id", "protocol-form-dialog-p-button-cancel", 3, "click", "label"], ["data-test-id", "protocol-form-dialog-p-button-save", 3, "click", "label"]], template: function ProtocolFormDialog_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](1, ProtocolFormDialog_Conditional_1_Template, 7, 8); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_0_0 = ctx.formDefinition()) ? 1 : -1, tmp_0_0); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_4__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_4__.Button, _protocol_form_protocol_form_component__WEBPACK_IMPORTED_MODULE_7__.ProtocolFormComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 51430 /*!*********************************************************************************!*\ !*** ./libs/feature/src/lib/protocols/protocol-form/protocol-form.component.ts ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolFormComponent: () => (/* binding */ ProtocolFormComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_checkbox__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/checkbox */ 10026); /* harmony import */ var primeng_fieldset__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/fieldset */ 48749); /* harmony import */ var primeng_radiobutton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/radiobutton */ 93522); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_textarea__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/textarea */ 25683); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_validators__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/validators */ 74208); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ standalone: true }); const _forTrack0 = ($index, $item) => $item.key; const _forTrack1 = ($index, $item) => $item.value; function ProtocolFormComponent_For_2_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](2, 1, ctx)); } } function ProtocolFormComponent_For_2_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p", 3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](2, 1, ctx)); } } function ProtocolFormComponent_For_2_Conditional_0_Case_3_Case_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 4)(1, "div", 5)(2, "p-radiobutton", 6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function ProtocolFormComponent_For_2_Conditional_0_Case_3_Case_0_Template_p_radiobutton_ngModelChange_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setFieldValue(fieldDef_r2, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "label", 7); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](4, "Yes"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](5, "div", 5)(6, "p-radiobutton", 8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function ProtocolFormComponent_For_2_Conditional_0_Case_3_Case_0_Template_p_radiobutton_ngModelChange_6_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setFieldValue(fieldDef_r2, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](7, "label", 9); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](8, "No"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()()(); } if (rf & 2) { const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("ngModel", ctx_r2.values()[fieldDef_r2.key])("name", fieldDef_r2.key)("value", true); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("ngModel", ctx_r2.values()[fieldDef_r2.key])("name", fieldDef_r2.key)("value", false); } } function ProtocolFormComponent_For_2_Conditional_0_Case_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](0, ProtocolFormComponent_For_2_Conditional_0_Case_3_Case_0_Template, 9, 6, "div", 4); } if (rf & 2) { let tmp_12_0; const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_12_0 = fieldDef_r2.representation) === "radio" ? 0 : -1); } } function ProtocolFormComponent_For_2_Conditional_0_Case_4_Case_0_For_2_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 5)(1, "p-checkbox", 10); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function ProtocolFormComponent_For_2_Conditional_0_Case_4_Case_0_For_2_Template_p_checkbox_ngModelChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](4).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setFieldValue(fieldDef_r2, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](2, "label", 11); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { const option_r5 = ctx.$implicit; const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](4).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("ngModel", ctx_r2.values()[fieldDef_r2.key])("name", fieldDef_r2.key)("inputId", option_r5.value)("value", option_r5.value)("disabled", ctx_r2.isOptionDisabled(fieldDef_r2, option_r5.value))("ngModelOptions", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction0"](10, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵattribute"]("data-test-id", `protocol-form-p-checkbox-${fieldDef_r2.key}-${option_r5.value}`); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("pTooltip", option_r5.description)("for", option_r5.value); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", option_r5.label, " "); } } function ProtocolFormComponent_For_2_Conditional_0_Case_4_Case_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeaterCreate"](1, ProtocolFormComponent_For_2_Conditional_0_Case_4_Case_0_For_2_Template, 4, 11, "div", 5, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeater"](ctx_r2.fieldOptions(fieldDef_r2)); } } function ProtocolFormComponent_For_2_Conditional_0_Case_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](0, ProtocolFormComponent_For_2_Conditional_0_Case_4_Case_0_Template, 3, 0, "div", 4); } if (rf & 2) { let tmp_12_0; const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_12_0 = fieldDef_r2.representation) === "checkboxes" ? 0 : -1); } } function ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_0_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-select", 14); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_0_Template_p_select_ngModelChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setFieldValue(fieldDef_r2, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("name", fieldDef_r2.key)("ngModel", ctx_r2.values()[fieldDef_r2.key])("options", ctx_r2.fieldOptions(fieldDef_r2)); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵattribute"]("data-test-id", `protocol-form-p-select-${fieldDef_r2.key}`); } } function ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_1_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "textarea", 15); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_1_Template_textarea_ngModelChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r7); const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.setFieldValue(fieldDef_r2, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](3).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("name", fieldDef_r2.key)("ngModel", ctx_r2.values()[fieldDef_r2.key]); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵattribute"]("data-test-id", `protocol-form-textarea-${fieldDef_r2.key}`); } } function ProtocolFormComponent_For_2_Conditional_0_Case_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](0, ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_0_Template, 1, 4, "p-select", 12)(1, ProtocolFormComponent_For_2_Conditional_0_Case_5_Case_1_Template, 1, 3, "textarea", 13); } if (rf & 2) { let tmp_12_0; const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_12_0 = fieldDef_r2.representation) === "select" ? 0 : tmp_12_0 === "textarea" ? 1 : -1); } } function ProtocolFormComponent_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-fieldset", 1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](1, ProtocolFormComponent_For_2_Conditional_0_Conditional_1_Template, 3, 3, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](2, ProtocolFormComponent_For_2_Conditional_0_Conditional_2_Template, 3, 3, "p", 3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](3, ProtocolFormComponent_For_2_Conditional_0_Case_3_Template, 1, 1)(4, ProtocolFormComponent_For_2_Conditional_0_Case_4_Template, 1, 1)(5, ProtocolFormComponent_For_2_Conditional_0_Case_5_Template, 2, 1); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_12_0; let tmp_13_0; let tmp_14_0; const fieldDef_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"]().$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("legend", ctx_r2.fieldLabel(fieldDef_r2)); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_12_0 = ctx_r2.fieldDescription(fieldDef_r2)) ? 1 : -1, tmp_12_0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_13_0 = ctx_r2.fieldError(fieldDef_r2)) ? 2 : -1, tmp_13_0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"]((tmp_14_0 = fieldDef_r2.valueType) === "boolean" ? 3 : tmp_14_0 === "multi-text" ? 4 : tmp_14_0 === "text" ? 5 : -1); } } function ProtocolFormComponent_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](0, ProtocolFormComponent_For_2_Conditional_0_Template, 6, 4, "p-fieldset", 1); } if (rf & 2) { const fieldDef_r2 = ctx.$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx_r2.isFieldVisible(fieldDef_r2) ? 0 : -1); } } class ProtocolFormComponent { translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateService); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_12__.ProtocolFacade); formDefinition = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "formDefinition" }] : [])); formValues = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "formValues" }] : [])); values = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.linkedSignal)(() => this.enforceExclusiveOptions(this.clearHiddenFields({ ...this.formValues() })), ...(ngDevMode ? [{ debugName: "values" }] : [])); validation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const definition = this.formDefinition(); const values = this.values(); return (0,_tomoverse_validators__WEBPACK_IMPORTED_MODULE_13__.validateProtocolForm)(definition.validation, values); }, ...(ngDevMode ? [{ debugName: "validation" }] : [])); isValid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.validation().valid, ...(ngDevMode ? [{ debugName: "isValid" }] : [])); save() { const { definition } = this.protocolFacade.activeProtocol(); if (definition) { this.protocolFacade.setFormValues(definition.id, this.values()); } } fieldLabel(field) { return (field.label ?? this.translate.instant(`protocolDef.tavi.form.${field.key}.label`)) || field.key; } fieldDescription(field) { return (field.description ?? this.translate.instant(`protocolDef.tavi.form.${field.key}.description`)) || undefined; } fieldOptions(field) { if (field.valueType === 'text' && field.representation === 'select' || field.valueType === 'multi-text') { return field.options.map(option => ({ description: option.description ?? this.translate.instant(`protocolDef.tavi.form.${field.key}.options.${option.value}.description`), label: option.label ?? this.translate.instant(`protocolDef.tavi.form.${field.key}.options.${option.value}.label`), value: option.value })); } return []; } isFieldVisible(field, values = this.values()) { return field.visibleWhen === undefined || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_11__.isPass)((0,_tomoverse_validators__WEBPACK_IMPORTED_MODULE_13__.validateProtocolFormField)(field.visibleWhen, field.key, values)); } setFieldValue(field, value) { this.values.update(previous => this.enforceExclusiveOptions(this.clearHiddenFields({ ...previous, [field.key]: value }))); } /** True while a different, exclusive option is selected on this field. */ isOptionDisabled(field, optionValue) { const exclusive = this.exclusiveValues(field); if (exclusive.length === 0) return false; const selected = this.values()[field.key]; if (!Array.isArray(selected)) return false; return selected.some(value => value !== optionValue && exclusive.includes(value)); } exclusiveValues(field) { if (!('options' in field)) return []; return field.options.filter(option => option.exclusive === true).map(o => o.value); } /** Collapses a multi-select field to a selected exclusive option, dropping anything it was * combined with - covers checking it last, and values persisted before the rule existed. */ enforceExclusiveOptions(values) { const nextValues = { ...values }; for (const field of this.formDefinition().fields) { const exclusive = this.exclusiveValues(field); if (exclusive.length === 0) continue; const selected = nextValues[field.key]; if (!Array.isArray(selected) || selected.length <= 1) continue; const chosen = selected.find(value => exclusive.includes(value)); if (chosen !== undefined) nextValues[field.key] = [chosen]; } return nextValues; } fieldError(field) { return this.validation().errors[field.key]; } clearHiddenFields(values) { const nextValues = { ...values }; for (const field of this.formDefinition().fields) { if (field.visibleWhen !== undefined && !this.isFieldVisible(field, nextValues)) { delete nextValues[field.key]; } } return nextValues; } static ɵfac = function ProtocolFormComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolFormComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵdefineComponent"]({ type: ProtocolFormComponent, selectors: [["lib-protocol-form"]], inputs: { formDefinition: [1, "formDefinition"], formValues: [1, "formValues"] }, decls: 3, vars: 0, consts: [[1, "flex", "flex-col", "gap-4"], [3, "legend"], [1, "mb-2", "text-xs"], [1, "mb-2", "text-xs", "text-(--p-app-status-danger)"], [1, "flex", "flex-wrap", "gap-4"], [1, "flex", "items-center", "gap-1"], ["inputId", "yes", 3, "ngModelChange", "ngModel", "name", "value"], ["for", "yes"], ["inputId", "no", 3, "ngModelChange", "ngModel", "name", "value"], ["for", "no"], [3, "ngModelChange", "ngModel", "name", "inputId", "value", "disabled", "ngModelOptions"], [3, "pTooltip", "for"], ["optionLabel", "label", "optionValue", "value", 1, "min-w-48", 3, "name", "ngModel", "options"], ["pTextarea", "", "fluid", "", 3, "name", "ngModel"], ["optionLabel", "label", "optionValue", "value", 1, "min-w-48", 3, "ngModelChange", "name", "ngModel", "options"], ["pTextarea", "", "fluid", "", 3, "ngModelChange", "name", "ngModel"]], template: function ProtocolFormComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "form", 0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeaterCreate"](1, ProtocolFormComponent_For_2_Template, 1, 1, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeater"](ctx.formDefinition().fields); } }, dependencies: [primeng_checkbox__WEBPACK_IMPORTED_MODULE_5__.CheckboxModule, primeng_checkbox__WEBPACK_IMPORTED_MODULE_5__.Checkbox, primeng_fieldset__WEBPACK_IMPORTED_MODULE_6__.FieldsetModule, primeng_fieldset__WEBPACK_IMPORTED_MODULE_6__.Fieldset, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_3__["ɵNgNoValidate"], _angular_forms__WEBPACK_IMPORTED_MODULE_3__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatusGroup, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgModel, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgForm, primeng_radiobutton__WEBPACK_IMPORTED_MODULE_7__.RadioButtonModule, primeng_radiobutton__WEBPACK_IMPORTED_MODULE_7__.RadioButton, primeng_select__WEBPACK_IMPORTED_MODULE_8__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_8__.Select, primeng_textarea__WEBPACK_IMPORTED_MODULE_9__.TextareaModule, primeng_textarea__WEBPACK_IMPORTED_MODULE_9__.Textarea, primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 52569 /*!*************************************************************************************************************************!*\ !*** ./libs/feature/src/lib/relative-measurements/relative-measurement-dialog/relative-measurement-dialog.component.ts ***! \*************************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RelativeMeasurementDialogComponent: () => (/* binding */ RelativeMeasurementDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _relative_measurements_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../relative-measurements.service */ 79408); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = a0 => ({ color: a0 }); const _c1 = a0 => ({ $implicit: a0 }); function RelativeMeasurementDialogComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelement"](1, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](2, "span", 11); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()(); } if (rf & 2) { const annotation_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("icon", annotation_r2.type)("iconStyle", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpureFunction1"](3, _c0, annotation_r2.color)); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtextInterpolate1"](" ", annotation_r2.name, " "); } } function RelativeMeasurementDialogComponent_Conditional_3_ng_template_1_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementContainer"](0); } } function RelativeMeasurementDialogComponent_Conditional_3_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](0, RelativeMeasurementDialogComponent_Conditional_3_ng_template_1_ng_container_0_Template, 1, 0, "ng-container", 13); } if (rf & 2) { const item_r5 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const itemTemplate_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("ngTemplateOutlet", itemTemplate_r6)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpureFunction1"](2, _c1, item_r5)); } } function RelativeMeasurementDialogComponent_Conditional_3_ng_template_3_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementContainer"](0); } } function RelativeMeasurementDialogComponent_Conditional_3_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](0, RelativeMeasurementDialogComponent_Conditional_3_ng_template_3_ng_container_0_Template, 1, 0, "ng-container", 13); } if (rf & 2) { const item_r7 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const itemTemplate_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("ngTemplateOutlet", itemTemplate_r6)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpureFunction1"](2, _c1, item_r7)); } } function RelativeMeasurementDialogComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p-select", 12); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function RelativeMeasurementDialogComponent_Conditional_3_Template_p_select_ngModelChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r3.target1, $event) || (ctx_r3.target1 = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](1, RelativeMeasurementDialogComponent_Conditional_3_ng_template_1_Template, 1, 4, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"])(3, RelativeMeasurementDialogComponent_Conditional_3_ng_template_3_Template, 1, 4, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r3.target1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("options", ctx_r3.target1Items()); } } function RelativeMeasurementDialogComponent_Conditional_4_ng_template_1_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementContainer"](0); } } function RelativeMeasurementDialogComponent_Conditional_4_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](0, RelativeMeasurementDialogComponent_Conditional_4_ng_template_1_ng_container_0_Template, 1, 0, "ng-container", 13); } if (rf & 2) { const item_r9 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const itemTemplate_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("ngTemplateOutlet", itemTemplate_r6)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpureFunction1"](2, _c1, item_r9)); } } function RelativeMeasurementDialogComponent_Conditional_4_ng_template_3_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementContainer"](0); } } function RelativeMeasurementDialogComponent_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](0, RelativeMeasurementDialogComponent_Conditional_4_ng_template_3_ng_container_0_Template, 1, 0, "ng-container", 13); } if (rf & 2) { const item_r10 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](2); const itemTemplate_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("ngTemplateOutlet", itemTemplate_r6)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpureFunction1"](2, _c1, item_r10)); } } function RelativeMeasurementDialogComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](0, "p-select", 14); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayListener"]("ngModelChange", function RelativeMeasurementDialogComponent_Conditional_4_Template_p_select_ngModelChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayBindingSet"](ctx_r3.target2, $event) || (ctx_r3.target2 = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](1, RelativeMeasurementDialogComponent_Conditional_4_ng_template_1_Template, 1, 4, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"])(3, RelativeMeasurementDialogComponent_Conditional_4_ng_template_3_Template, 1, 4, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtwoWayProperty"]("ngModel", ctx_r3.target2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("options", ctx_r3.target2Items()); } } const anyAnnotation = () => true; function not(filter) { return annotation => filter(annotation) === false; } function or(...filters) { return annotation => filters.some(filter => filter(annotation)); } const RELATIONSHIP_FILTERS = { 'angle-between-spline-axes': [_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsClosedSpline, _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsClosedSpline], 'angle-between-splines': [_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsClosedSpline, _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsClosedSpline], 'attached-distance': [not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsPoint)], 'attached-point': [not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsPoint)], 'attached-spline': [not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsPoint)], 'center-distance': [not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsPoint)], chord: [or(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsSpline, _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsAngle)], 'closest-distance-between-annotations': [not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsObject3D), not(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsObject3D)], 'closest-distance-to-one-annotation': [anyAnnotation], 'curvature-point': [_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsSpline], 'distance-between': [anyAnnotation, anyAnnotation], 'projected-distance': [_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsSpline], 'projected-distance-from-point': [_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsSpline, _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_9__.annotationIsPoint] }; class RelativeMeasurementDialogComponent { dialogReference = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_7__.DynamicDialogRef); relativeMeasurementsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_relative_measurements_service__WEBPACK_IMPORTED_MODULE_11__.RelativeMeasurementsService); annotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)([], ...(ngDevMode ? [{ debugName: "annotations" }] : [])); relationshipType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('angle-between-spline-axes', ...(ngDevMode ? [{ debugName: "relationshipType" }] : [])); filters = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const relationshipType = this.relationshipType(); return RELATIONSHIP_FILTERS[relationshipType] ?? []; }, ...(ngDevMode ? [{ debugName: "filters" }] : [])); target1Items = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const annotations = this.annotations(); const [filter] = this.filters(); if (!filter) return; return annotations.filter(annotation => filter(annotation)); }, ...(ngDevMode ? [{ debugName: "target1Items" }] : [])); target2Items = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const annotations = this.annotations(); const target1 = this.target1(); const [, filter] = this.filters(); if (!filter) return; return annotations.filter(annotation => filter(annotation) && annotation !== target1); }, ...(ngDevMode ? [{ debugName: "target2Items" }] : [])); target1 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.linkedSignal)(() => this.target1Items()?.[0], ...(ngDevMode ? [{ debugName: "target1" }] : [])); target2 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.linkedSignal)(() => this.target2Items()?.[0], ...(ngDevMode ? [{ debugName: "target2" }] : [])); isValid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const [a, b] = this.filters(); const [target1, target2] = [this.target1(), this.target2()]; if (a !== undefined && target1 === undefined) return false; if (b !== undefined && target2 === undefined) return false; return true; }, ...(ngDevMode ? [{ debugName: "isValid" }] : [])); cancel() { this.dialogReference.close(); } confirm() { const sources = [this.target1(), this.target2()].filter(annotation => annotation !== undefined); this.relativeMeasurementsService.create(this.relationshipType(), sources); this.dialogReference.close(); } static ɵfac = function RelativeMeasurementDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RelativeMeasurementDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵdefineComponent"]({ type: RelativeMeasurementDialogComponent, selectors: [["lib-relative-measurement-dialog"]], inputs: { annotations: [1, "annotations"], relationshipType: [1, "relationshipType"] }, decls: 10, vars: 9, consts: [["itemTemplate", ""], ["item", ""], ["selectedItem", ""], [1, "flex", "flex-col", "gap-4", "p-4"], ["appendTo", "body", "optionLabel", "name", "data-test-id", "relative-measurement-dialog-p-select-target1", 3, "ngModel", "options"], ["appendTo", "body", "optionLabel", "name", "data-test-id", "relative-measurement-dialog-p-select-target2", 3, "ngModel", "options"], [1, "flex", "justify-end", "gap-2"], ["severity", "secondary", "variant", "text", "data-test-id", "relative-measurement-dialog-p-button-cancel", 3, "click", "label"], ["data-test-id", "relative-measurement-dialog-p-button-confirm", 3, "click", "label", "disabled"], [1, "flex", "items-center", "gap-2"], [1, "size-(--p-app-icon-size-xs)", 3, "icon", "iconStyle"], [1, "max-w-64", "overflow-hidden", "text-ellipsis", "whitespace-nowrap"], ["appendTo", "body", "optionLabel", "name", "data-test-id", "relative-measurement-dialog-p-select-target1", 3, "ngModelChange", "ngModel", "options"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], ["appendTo", "body", "optionLabel", "name", "data-test-id", "relative-measurement-dialog-p-select-target2", 3, "ngModelChange", "ngModel", "options"]], template: function RelativeMeasurementDialogComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplate"](0, RelativeMeasurementDialogComponent_ng_template_0_Template, 4, 5, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](2, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](3, RelativeMeasurementDialogComponent_Conditional_3_Template, 5, 2, "p-select", 4); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditionalCreate"](4, RelativeMeasurementDialogComponent_Conditional_4_Template, 5, 2, "p-select", 5); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](5, "div", 6)(6, "p-button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function RelativeMeasurementDialogComponent_Template_p_button_click_6_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.cancel()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementStart"](8, "p-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵlistener"]("click", function RelativeMeasurementDialogComponent_Template_p_button_click_8_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.confirm()); }); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.target1Items() ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵconditional"](ctx.target2Items() ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](7, 5, "common.cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_12__["ɵɵpipeBind1"](9, 7, "common.create"))("disabled", !ctx.isValid()); } }, dependencies: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_10__.IconComponent, primeng_button__WEBPACK_IMPORTED_MODULE_6__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_6__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_4__.NgModel, primeng_select__WEBPACK_IMPORTED_MODULE_8__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_8__.Select, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslateModule, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 79408 /*!*************************************************************************************!*\ !*** ./libs/feature/src/lib/relative-measurements/relative-measurements.service.ts ***! \*************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RelativeMeasurementsService: () => (/* binding */ RelativeMeasurementsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../colors/colors.service */ 39298); class RelativeMeasurementsService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.AnnotationFacade); colorsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_5__.ColorsService); INVALID_SOURCES = 'Invalid sources provided'; // eslint-disable-next-line sonarjs/cognitive-complexity, sonarjs/cyclomatic-complexity create(type, sources) { switch (type) { case 'angle-between-spline-axes': { const [a, b] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(a) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(b)) { console.warn(this.INVALID_SOURCES); return; } this.angleBetweenSplineAxes(a, b); break; } case 'angle-between-splines': { const [a, b] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(a) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(b)) { console.warn(this.INVALID_SOURCES); return; } this.angleBetweenSplines(a, b); break; } case 'attached-distance': { const [source] = sources; if (source === undefined || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsPoint)(source)) { console.warn(this.INVALID_SOURCES); return; } this.attachedDistance(source); break; } case 'attached-point': { const [source] = sources; if (source === undefined || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsPoint)(source)) { console.warn(this.INVALID_SOURCES); return; } this.attachedPoint(source); break; } case 'attached-spline': { const [source] = sources; if (source === undefined || (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsPoint)(source)) { console.warn(this.INVALID_SOURCES); return; } this.attachedSpline(source); break; } case 'center-distance': { const [source] = sources; if (source === undefined) { console.warn(this.INVALID_SOURCES); return; } this.centerDistance(source); break; } case 'chord': { const [source] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsSpline)(source) && !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsAngle)(source)) { console.warn(this.INVALID_SOURCES); return; } this.chord(source); break; } case 'closest-distance-between-annotations': { const [a, b] = sources; if (a === undefined || b === undefined) { console.warn(this.INVALID_SOURCES); return; } this.closestDistanceBetween(a, b); break; } case 'closest-distance-to-one-annotation': { const [source] = sources; if (source === undefined) { console.warn(this.INVALID_SOURCES); return; } this.closestDistance(source); break; } case 'curvature-point': { const [source] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsSpline)(source)) { console.warn(this.INVALID_SOURCES); return; } this.curvaturePoint(source); break; } case 'distance-between': { // Unsupported break; } case 'projected-distance': { const [source] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsSpline)(source)) { console.warn(this.INVALID_SOURCES); return; } this.projectedDistance(source); break; } case 'projected-distance-from-point': { const [a, b] = sources; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsSpline)(a) || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsPoint)(b)) { console.warn(this.INVALID_SOURCES); return; } this.projectedDistanceFromPoint(a, b); break; } } } angleBetweenSplineAxes(target, to) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.angle)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Angle Between Spline Axes', this.annotationNames()), points: [[0, 0, 0], [0, 0, 0], [0, 0, 0]], relationship: { sourceIds: [target.id, to.id], type: 'angle-between-spline-axes' } })); this.annotationFacade.annotationCreationComplete(); } angleBetweenSplines(target, to) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.angle)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Angle Between Splines', this.annotationNames()), points: [[0, 0, 0], [0, 0, 0], [0, 0, 0]], relationship: { sourceIds: [target.id, to.id], type: 'angle-between-splines' } })); this.annotationFacade.annotationCreationComplete(); } attachedDistance(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Attached Distance', this.annotationNames()), points: [], relationship: { sourceIds: [target.id], type: 'attached-distance' } })); } attachedPoint(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.point)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Attached Point', this.annotationNames()), position: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.ORIGIN, relationship: { sourceIds: [target.id], type: 'attached-point' } })); } attachedSpline(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.openSpline)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Attached Spline', this.annotationNames()), points: [], relationship: { sourceIds: [target.id], type: 'attached-spline' } })); } centerDistance(target) { const centroid = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(target); this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Center Distance', this.annotationNames()), points: [centroid], relationship: { sourceIds: [target.id], type: 'center-distance' } })); } chord(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Chord', this.annotationNames()), points: [], relationship: { sourceIds: [target.id], type: 'chord' } })); } closestDistance(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Closest Distance', this.annotationNames()), points: [[0, 0, 0]], relationship: { sourceIds: [target.id], type: 'closest-distance-to-one-annotation' } })); } closestDistanceBetween(target, to) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Distance Between Annotations', this.annotationNames()), points: [[0, 0, 0], [0, 0, 0]], relationship: { sourceIds: [target.id, to.id], type: 'closest-distance-between-annotations' } })); this.annotationFacade.annotationCreationComplete(); } curvaturePoint(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.point)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Curvature Point', this.annotationNames()), position: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.ORIGIN, relationship: { sourceIds: [target.id], type: 'curvature-point' } })); } projectedDistance(target) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Projected Distance', this.annotationNames()), points: [(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(target)], relationship: { sourceIds: [target.id], type: 'projected-distance' } })); } projectedDistanceFromPoint(target, targetPoint) { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.distance)({ color: this.colorsService.currentColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.incrementName)('Projected Distance From Point', this.annotationNames()), points: [(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_2__.getCentroid)(target), [...targetPoint.position]], relationship: { sourceIds: [target.id, targetPoint.id], type: 'projected-distance-from-point' } })); this.annotationFacade.annotationCreationComplete(); } annotationNames() { return this.annotationFacade.annotations().map(ann => ann.name); } static ɵfac = function RelativeMeasurementsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RelativeMeasurementsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: RelativeMeasurementsService, factory: RelativeMeasurementsService.ɵfac }); } /***/ }, /***/ 31982 /*!*********************************************************************!*\ !*** ./libs/feature/src/lib/s-curve-card/s-curve-card.component.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveCardComponent: () => (/* binding */ SCurveCardComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../annotation-menu/directives/annotation-menu-trigger.directive */ 12564); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../card-theme/card-theme */ 92147); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["nameInput"]; const _c1 = () => ({ root: "size-6" }); const _c2 = () => ({ color: "var(--p-accordion-header-toggle-icon-color)" }); const _c3 = a0 => ({ secondary: a0 }); const _c4 = a0 => ({ outlined: a0 }); const _c5 = () => ({ root: "py-1 px-0" }); const _forTrack0 = ($index, $item) => $item.name; const _forTrack1 = ($index, $item) => $item.icon; function SCurveCardComponent_ng_container_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_Conditional_5_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](0, SCurveCardComponent_Conditional_5_ng_container_0_Template, 1, 0, "ng-container", 14); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); const dragHandle_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](27); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", dragHandle_r2); } } function SCurveCardComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 22); } if (rf & 2) { const active_r3 = ctx.active; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵclassMap"](ctx_r3.cn("p-accordionheader-toggle-icon size-(--p-app-icon-size-xxs) text-(length:--p-app-icon-size-xxs)", !ctx_r3.cdkDrag() && "ml-2.5")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("icon", active_r3 ? "chevron-down" : "chevron-right"); } } function SCurveCardComponent_ng_container_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_ng_container_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_Conditional_12_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](0, SCurveCardComponent_Conditional_12_ng_container_0_Template, 1, 0, "ng-container", 14); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); const moreMenuBtn_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](31); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", moreMenuBtn_r5); } } function SCurveCardComponent_ng_container_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 20)(1, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](2, "Spline:"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](3, "span", 24); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", ctx_r3.sCurve().name, " "); } } function SCurveCardComponent_For_19_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 20)(1, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](3, "span", 24); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const view_r6 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"]("", view_r6.name, ":"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", view_r6.angulation, " "); } } function SCurveCardComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 21)(1, "lib-slider", 25); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("sliderChanged", function SCurveCardComponent_Conditional_20_Template_lib_slider_sliderChanged_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.onSliderChange($event)); })("slideEnd", function SCurveCardComponent_Conditional_20_Template_lib_slider_slideEnd_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r7); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.onSlideEnd()); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("sliderClassName", "flex w-full flex-grow pointer-events-auto")("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.001)("sliderValue", ctx_r3.curvePosition()); } } function SCurveCardComponent_ng_container_21_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 33); } } function SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r9 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "p-button", 32); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("mousedown", function SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_Template_p_button_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r9); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.preventDefault()); })("click", function SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r9); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.clearName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](3, SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_ng_template_3_Template, 1, 0, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](1, 3, "common.clearName"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](2, 5, "common.clearName"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction0"](7, _c1)); } } function SCurveCardComponent_ng_template_22_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 27)(1, "input", 30, 9); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("click", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_click_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keydown.space", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keydown_space_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keyup.space", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keyup_space_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keydown.enter", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keydown_enter_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation()($event)); })("keyup.enter", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keyup_enter_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.commitEditName)($event)); })("keydown.escape", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keydown_escape_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation()($event)); })("keyup.escape", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_keyup_escape_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.cancelEditName)($event)); })("blur", function SCurveCardComponent_ng_template_22_Conditional_1_Template_input_blur_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.commitEditName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](4, SCurveCardComponent_ng_template_22_Conditional_1_Conditional_4_Template, 5, 8, "p-button", 31); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("formControl", ctx_r3.sCurveName); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵattribute"]("data-test-id", "s-curve-card-input-" + ctx_r3.sCurve().id + "-name")("maxlength", ctx_r3.nameMaxLength)("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](3, 5, "common.name")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx_r3.sCurveName.value ? 4 : -1); } } function SCurveCardComponent_ng_template_22_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r10 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "button", 34); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("click", function SCurveCardComponent_ng_template_22_Conditional_2_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r10); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.onEditName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](1, "span", 29); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵattribute"]("data-test-id", "s-curve-card-button-" + ctx_r3.sCurve().id + "-name-trigger"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate"](ctx_r3.sCurve().name); } } function SCurveCardComponent_ng_template_22_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "span", 29); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtextInterpolate1"](" ", ctx_r3.sCurve().name, " "); } } function SCurveCardComponent_ng_template_22_Conditional_4_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementContainer"](0); } } function SCurveCardComponent_ng_template_22_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](0, SCurveCardComponent_ng_template_22_Conditional_4_ng_container_0_Template, 1, 0, "ng-container", 14); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); const visibilityBtn_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](29); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", visibilityBtn_r11); } } function SCurveCardComponent_ng_template_22_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 26); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](1, SCurveCardComponent_ng_template_22_Conditional_1_Template, 5, 7, "div", 27)(2, SCurveCardComponent_ng_template_22_Conditional_2_Template, 3, 2, "button", 28)(3, SCurveCardComponent_ng_template_22_Conditional_3_Template, 2, 1, "span", 29); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](4, SCurveCardComponent_ng_template_22_Conditional_4_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx_r3.isEditingName() ? 1 : ctx_r3.canRenameInline() ? 2 : 3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](!ctx_r3.isEditingName() ? 4 : -1); } } function SCurveCardComponent_ng_template_24_Template(rf, ctx) { if (rf & 1) { const _r12 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 35); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("dblclick", function SCurveCardComponent_ng_template_24_Template_div_dblclick_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r12); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.goTo.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](1, "lib-icon", 36); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵclassMap"](ctx_r3.cn("bg-surface-900 flex size-7.5 shrink-0 items-center justify-center rounded-full", ctx_r3.sCurve().hidden && "opacity-80")); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵstyleProp"]("color", ctx_r3.accentColor()); } } function SCurveCardComponent_ng_template_26_div_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "div", 39); } } function SCurveCardComponent_ng_template_26_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 37); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](2, SCurveCardComponent_ng_template_26_div_2_Template, 1, 0, "div", 38); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](1, 1, "annotationCard.dragToReorder")); } } function SCurveCardComponent_ng_template_28_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 41); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("icon", ctx_r3.sCurve().hidden ? "eye" : "eye-off"); } } function SCurveCardComponent_ng_template_28_Template(rf, ctx) { if (rf & 1) { const _r13 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "p-button", 40); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("click", function SCurveCardComponent_ng_template_28_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r13); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.sCurve().hidden ? ctx_r3.show.emit() : ctx_r3.hide.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](2, SCurveCardComponent_ng_template_28_ng_template_2_Template, 1, 1, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](7, _c4, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](5, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction0"](4, _c2))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](1, 2, ctx_r3.sCurve().hidden ? "common.show" : "common.hide")); } } function SCurveCardComponent_ng_template_30_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 43); } } function SCurveCardComponent_ng_template_30_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "p-button", 42); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](2, SCurveCardComponent_ng_template_30_ng_template_2_Template, 1, 0, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](9, _c4, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction1"](7, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction0"](6, _c2))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpipeBind1"](1, 4, "common.moreActions"))("libMenuTrigger", ctx_r3.menuTrigger())("libMenuActions", ctx_r3.actions()); } } function SCurveCardComponent_ng_template_32_For_2_Conditional_0_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "lib-icon", 47); } if (rf & 2) { const action_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("icon", action_r15.icon)("pTooltip", action_r15.label); } } function SCurveCardComponent_ng_template_32_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r14 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "p-button", 46); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("click", function SCurveCardComponent_ng_template_32_For_2_Conditional_0_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r14); const action_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"]().$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](action_r15.command == null ? null : action_r15.command($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](1, SCurveCardComponent_ng_template_32_For_2_Conditional_0_ng_template_1_Template, 1, 2, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const action_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵpureFunction0"](2, _c5))("disabled", action_r15.disabled); } } function SCurveCardComponent_ng_template_32_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](0, SCurveCardComponent_ng_template_32_For_2_Conditional_0_Template, 3, 3, "p-button", 45); } if (rf & 2) { const action_r15 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](action_r15.icon ? 0 : -1); } } function SCurveCardComponent_ng_template_32_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 44); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵrepeaterCreate"](1, SCurveCardComponent_ng_template_32_For_2_Template, 1, 1, null, null, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵrepeater"](ctx_r3.cardActions()); } } function SCurveCardComponent_ng_template_34_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelement"](0, "div", 48); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵstyleProp"]("background-color", ctx_r3.selected() ? ctx_r3.accentColor() : ""); } } class SCurveCardComponent { actions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)([], ...(ngDevMode ? [{ debugName: "actions" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); sCurve = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "sCurve" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "selected" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); menuTrigger = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(...(ngDevMode ? [undefined, { debugName: "menuTrigger" }] : [])); cdkDrag = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "cdkDrag" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_15__.AnnotationFacade); renderSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_15__.renderSettingsStore); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_15__.viewportStore); sliding = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "sliding" }] : [])); show = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); hide = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); goTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); clicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); updateName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); cancelClick = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__.CancelClickDirective, ...(ngDevMode ? [{ debugName: "cancelClick" }] : [])); nameInput = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameInput', ...(ngDevMode ? [{ debugName: "nameInput" }] : [])); isEditingName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isEditingName" }] : [])); sCurveName = new _angular_forms__WEBPACK_IMPORTED_MODULE_5__.FormControl(''); nameMaxLength = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.ANNOTATION_NAME_MAX_LENGTH; // Spline-derived s-curves inherit their name from the spline annotation — // only control-point (manually-authored) curves can be renamed here. canRenameInline = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_12__.sCurveIsControlPoint)(this.sCurve()), ...(ngDevMode ? [{ debugName: "canRenameInline" }] : [])); // protected readonly curvePosition = model(0.5); curvePosition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.linkedSignal)(() => { const { cc, rl } = this.viewportStore.angulations.coronal(); const path = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_14__.getSCurvePath)(this.sCurve()); const path3D = path.map(([x, y]) => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.position)(x, y, 0)); const distance = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.calculateDistanceOnPath)(path3D, [rl, cc, 0]); const length = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.calculatePathDistance)(path3D, false); return distance / length; }, ...(ngDevMode ? [{ debugName: "curvePosition" }] : [])); ngAfterViewInit() { this.cancelClick()?.filteredClick.subscribe(event => this.clicked.emit(event)); } mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_19__.buildCardPt)(this.pt(), this.cardState()), ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_19__.buildCardDt)(_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_19__.DARK_CARD_THEME[this.cardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); accentColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.sCurve().hidden ? 'var(--p-text-muted-color)' : this.sCurve().color, ...(ngDevMode ? [{ debugName: "accentColor" }] : [])); cardActions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.actions().filter(action => action.includeInCard), ...(ngDevMode ? [{ debugName: "cardActions" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_19__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.cn; contextMenu(event) { // NOTE: On Mac, ctrl+click triggers the contextmenu event, // but that conflicts with our multiselect functionality. // We must re-emit this as a click now if (event.ctrlKey) { event.preventDefault(); this.clicked.emit(event); return; } const trigger = this.menuTrigger(); if (!trigger) return; trigger.model.set(this.actions()); trigger.toggle(event); } views = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const sCurve = this.sCurve(); switch (sCurve.type) { case 'control-point': { const single = sCurve.controlPoints.length === 1; return sCurve.controlPoints.map(([rl, cc], index) => ({ angulation: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.formatAngulationtxt)({ ax: 0, cc, rl }, false), name: single ? 'On-curve view' : `On-curve view ${index + 1}` })); } case 'spline': { return [{ angulation: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.formatAngulationtxt)((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_14__.getSCurveEnFaceAngle)(sCurve), false), name: 'En-face view' }]; } } }, ...(ngDevMode ? [{ debugName: "views" }] : [])); cardState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const isHidden = this.sCurve().hidden; const isSelected = this.selected(); if (isHidden) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DISABLED; if (isSelected) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.SELECTED; return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.CardState.DEFAULT; }, ...(ngDevMode ? [{ debugName: "cardState" }] : [])); onSliderChange(value) { this.renderSettings.lowQualityWithTimeout(); const curve = this.sCurve(); if (!this.sliding()) { // Control-point curves have no backing annotation to center the camera // on — only spline-derived curves do. if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_12__.sCurveIsSpline)(curve)) { this.annotationFacade.goToAnnotation(curve.id, true); } this.sliding.set(true); } const path = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_14__.getSCurvePath)(curve); const point = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.getPointAtDistance)(path, value); if (point) { const [rl, cc] = point; const newPosVec = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.angulationToVector)({ ax: 0, cc, rl }); const enFace = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_14__.getSCurveEnFaceAngle)(curve); const enFaceVec = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.angulationToVector)(enFace); const cross = gl_matrix__WEBPACK_IMPORTED_MODULE_7__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_7__.create(), newPosVec, enFaceVec); this.viewportStore.updateAngulationsForAllAxes({ ax: 0, cc, rl }, enFace, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_17__.vec3ToPosition)(cross))); } } onSlideEnd() { this.renderSettings.setLowQuality(false); this.sliding.set(false); } onEditName = () => { if (this.isEditingName() || !this.canRenameInline()) return; this.sCurveName.setValue(this.sCurve().name); this.menuTrigger()?.hide(); this.isEditingName.set(true); setTimeout(() => this.nameInput()?.nativeElement.focus()); }; cancelEditName = () => { this.isEditingName.set(false); }; /** Clears the field's current text (without saving), letting the name be retyped or * re-entered with the mouse alone, no backspacing required. */ clearName = () => { this.sCurveName.setValue(''); this.nameInput()?.nativeElement.focus(); }; commitEditName = () => { const value = this.sCurveName.value ?? ''; if (value.trim().length === 0) { this.cancelEditName(); return; } this.isEditingName.set(false); this.updateName.emit(value.trim()); }; handleNameEventPropagation(callback) { return event => { event.stopPropagation(); event.preventDefault(); callback?.(); }; } static ɵfac = function SCurveCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵdefineComponent"]({ type: SCurveCardComponent, selectors: [["lib-s-curve-card"]], viewQuery: function SCurveCardComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵviewQuerySignal"](ctx.cancelClick, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__.CancelClickDirective, 5)(ctx.nameInput, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵqueryAdvance"](2); } }, inputs: { actions: [1, "actions"], pt: [1, "pt"], sCurve: [1, "sCurve"], selected: [1, "selected"], menuTrigger: [1, "menuTrigger"], cdkDrag: [1, "cdkDrag"] }, outputs: { show: "show", hide: "hide", goTo: "goTo", clicked: "clicked", updateName: "updateName" }, decls: 36, vars: 18, consts: [["panel", ""], ["toggleicon", ""], ["headerTitle", ""], ["cardIcon", ""], ["dragHandle", ""], ["visibilityBtn", ""], ["moreMenuBtn", ""], ["contentActions", ""], ["accentBar", ""], ["nameInput", ""], ["icon", ""], [3, "click", "contextmenu"], [1, "grow", 3, "pt", "dt", "value"], ["libCancelClick", "", 1, "relative", 3, "pt"], [4, "ngTemplateOutlet"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-3", "py-0.5"], [1, "relative", 3, "pt"], [1, "flex", "gap-3"], [1, "flex", "grow", "flex-col", "gap-1", "py-1", "text-xs"], [1, "flex", "gap-1"], [1, "flex", "gap-1", "p-2"], ["data-propagate-click", "", 3, "icon"], [1, "text-color", "font-bold"], [1, "flex", "grow", "justify-end", "text-(--p-accordion-content-muted-color)"], ["dataTestIdOverride", "s-curve-card-slider-position", "name", "s-curve-card-position", 1, "min-w-0", "flex-1", 3, "sliderChanged", "slideEnd", "sliderClassName", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], [1, "flex", "min-w-0", "flex-1", "items-center", "gap-1"], ["type", "button", "data-propagate-click", "", 1, "min-w-0", "flex-1", "cursor-pointer", "text-left"], [1, "line-clamp-2", "wrap-anywhere"], ["pInputText", "", "data-propagate-click", "", 1, "border-primary-400", "bg-transparent", "py-0.5", "text-sm", "text-inherit", 3, "click", "keydown.space", "keyup.space", "keydown.enter", "keyup.enter", "keydown.escape", "keyup.escape", "blur", "formControl"], ["type", "button", "data-propagate-click", "", "data-test-id", "s-curve-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "pTooltip", "ariaLabel", "pt"], ["type", "button", "data-propagate-click", "", "data-test-id", "s-curve-card-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "mousedown", "click", "pTooltip", "ariaLabel", "pt"], ["icon", "times", 1, "size-3"], ["type", "button", "data-propagate-click", "", 1, "min-w-0", "flex-1", "cursor-pointer", "text-left", 3, "click"], [3, "dblclick"], ["icon", "s-curve", 1, "size-(--p-app-icon-size-sm)"], ["cdkDragHandle", "", "icon", "drag-handle", 1, "order-first", "size-3", "cursor-grab", "px-1.5", "py-3", "text-(--p-accordion-header-toggle-icon-hover-color)", "opacity-0", "transition-opacity", "delay-100", "group-hover:opacity-100", "active:cursor-grabbing"], ["class", "h-11 rounded-sm bg-(--p-app-dark-surface-base)", 4, "cdkDragPlaceholder"], [1, "h-11", "rounded-sm", "bg-(--p-app-dark-surface-base)"], ["data-test-id", "s-curve-card-p-button-visibility", "data-propagate-click", "", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "dt", "pTooltip"], [1, "size-(--p-app-icon-size-xs)", 3, "icon"], ["data-test-id", "s-curve-card-p-button-more-actions", "data-propagate-click", "", "severity", "secondary", "outlined", "", "size", "small", 3, "dt", "pTooltip", "libMenuTrigger", "libMenuActions"], ["icon", "ellipsis-v", 1, "size-(--p-app-icon-size-xxxs)", "text-(length:--p-app-icon-size-xxxs)"], [1, "flex", "flex-col", "items-center"], ["data-test-id", "s-curve-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "pt", "disabled"], ["data-test-id", "s-curve-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "pt", "disabled"], [1, "size-(--p-app-icon-size-sm)", 3, "icon", "pTooltip"], [1, "absolute", "top-0", "left-0", "h-full", "w-1"]], template: function SCurveCardComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](0, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵlistener"]("click", function SCurveCardComponent_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.clicked.emit($event)); })("contextmenu", function SCurveCardComponent_Template_div_contextmenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.contextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](1, "p-accordion-panel", 12, 0)(3, "p-accordion-header", 13); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](4, SCurveCardComponent_ng_container_4_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](5, SCurveCardComponent_Conditional_5_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](6, SCurveCardComponent_ng_template_6_Template, 1, 3, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](8, "div", 15)(9, "div", 16); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](10, SCurveCardComponent_ng_container_10_Template, 1, 0, "ng-container", 14)(11, SCurveCardComponent_ng_container_11_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](12, SCurveCardComponent_Conditional_12_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](13, "p-accordion-content", 17); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](14, SCurveCardComponent_ng_container_14_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementStart"](15, "div", 18)(16, "div", 19); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](17, SCurveCardComponent_Conditional_17_Template, 5, 1, "div", 20); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵrepeaterCreate"](18, SCurveCardComponent_For_19_Template, 5, 2, "div", 20, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditionalCreate"](20, SCurveCardComponent_Conditional_20_Template, 2, 5, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](21, SCurveCardComponent_ng_container_21_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplate"](22, SCurveCardComponent_ng_template_22_Template, 5, 2, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(24, SCurveCardComponent_ng_template_24_Template, 2, 4, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(26, SCurveCardComponent_ng_template_26_Template, 3, 3, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(28, SCurveCardComponent_ng_template_28_Template, 4, 9, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(30, SCurveCardComponent_ng_template_30_Template, 4, 11, "ng-template", null, 6, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(32, SCurveCardComponent_ng_template_32_Template, 3, 0, "ng-template", null, 7, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"])(34, SCurveCardComponent_ng_template_34_Template, 1, 2, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const headerTitle_r16 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](23); const cardIcon_r17 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](25); const contentActions_r18 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](33); const accentBar_r19 = _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵreference"](35); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵclassMap"](ctx.cn("group flex w-full overflow-hidden border-b border-(--p-app-border-subtle)", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", ctx.sCurve().id); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r19); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx.cdkDrag() ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r17); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", headerTitle_r16); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx.menuTrigger() && ctx.actions().length && !ctx.isEditingName() ? 12 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("pt", ctx.mergedPt().content); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r19); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx.sCurve().type === "spline" ? 17 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵrepeater"](ctx.views()); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵconditional"](ctx.cardState() === "selected" ? 20 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_20__["ɵɵproperty"]("ngTemplateOutlet", contentActions_r18); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionContent, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_8__.AccordionPanel, _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_18__.AnnotationMenuTriggerDirective, primeng_button__WEBPACK_IMPORTED_MODULE_9__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__.CancelClickDirective, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragHandle, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragPlaceholder, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__.IconComponent, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_10__.InputText, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_16__.SliderComponent, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.FormControlDirective, primeng_tooltip__WEBPACK_IMPORTED_MODULE_11__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 1336 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/s-curve-graph/s-curve-graph.component.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveGraphComponent: () => (/* binding */ SCurveGraphComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../annotation-menu/annotation-menu-item.service */ 39860); /* harmony import */ var _annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../annotation-menu/components/annotation-menu-item.component */ 45731); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["ctxMenu"]; const _c1 = () => ({ "--p-button-text-primary-color": "var(--p-app-graph-label)", "--p-button-text-primary-hover-background": "color-mix(in srgb, var(--p-app-graph-label) 10%, transparent)" }); function SCurveGraphComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "lib-viewport-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("click", function SCurveGraphComponent_Conditional_3_Template_lib_viewport_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.toggleMaximize.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipeBind1"](1, 3, ctx_r2.isMaximized() ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipeBind1"](2, 5, ctx_r2.isMaximized() ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel"))("icon", ctx_r2.isMaximized() ? "arrow-down-left-and-arrow-up-right-to-center" : "arrow-up-right-and-arrow-down-left-from-center"); } } function SCurveGraphComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "p-button", 9); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("click", function SCurveGraphComponent_Conditional_4_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.toggleDetach()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵstyleMap"](_angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](11, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("icon", ctx_r2.isDetached() ? "pi pi-window-minimize" : "pi pi-window-maximize")("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipeBind1"](1, 7, "viewportButton.sCurveToViewport"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipeBind1"](2, 9, "viewportButton.sCurveToViewport"))("rounded", true)("text", true); } } function SCurveGraphComponent_ng_template_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelement"](0, "lib-annotation-menu-item", 10); } if (rf & 2) { const item_r5 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("item", item_r5); } } const VIEWPORT_COLORS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.AXIAL]: 'var(--p-app-viewport-axis-axial)', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.CORONAL]: 'var(--p-app-viewport-axis-coronal)', [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.SAGITTAL]: 'var(--p-app-viewport-axis-sagittal)' }; const NUM_ROTATIONS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.AXIAL]: 2, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.CORONAL]: 0, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportAxis.SAGITTAL]: 1 }; const CONTROL_POINT_ID_PREFIX = 'cp:'; const INTERSECTION_POINT_ID_PREFIX = 'ix:'; const CHAMBER_POINT_ID_PREFIX = 'chamber:'; function intersectionPointId(measurementId) { return `${INTERSECTION_POINT_ID_PREFIX}${measurementId}`; } function chamberPointId(chamberId) { return `${CHAMBER_POINT_ID_PREFIX}${chamberId}`; } /** A control-point curve's own points can't reuse the ViewportAxis string keys * (a curveId is a uuid, so this can never collide with them). */ function controlPointId(curveId, index) { return `${CONTROL_POINT_ID_PREFIX}${curveId}:${index}`; } /** Parses a controlPointId back into its curveId/index, or undefined if pointId * isn't one (e.g. a ViewportAxis key). */ function parseControlPointId(pointId) { if (!pointId.startsWith(CONTROL_POINT_ID_PREFIX)) return undefined; const [curveId, indexText] = pointId.slice(CONTROL_POINT_ID_PREFIX.length).split(':'); const index = Number(indexText); if (!curveId || Number.isNaN(index)) return undefined; return { curveId, index }; } class SCurveGraphComponent { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.AnnotationFacade); chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.ChamberFacade); renderSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.renderSettingsStore); sCurveFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.SCurveFacade); uiFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.UiFacade); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_11__.viewportStore); menuItemService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_14__.AnnotationMenuItemService); menuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "menuItems" }] : [])); contextMenu = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('ctxMenu'); interacting = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "interacting" }] : [])); isDetached = this.uiFacade.sCurveGraphDetached; hoveredCurveId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "hoveredCurveId" }] : [])); hoveredPointId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "hoveredPointId" }] : [])); backgroundMenuItems = this.menuItemService.menuItemsForPanelSCurves(); toggleDetach() { if (this.isDetached()) { this.uiFacade.attachSCurveGraph(); } else { this.uiFacade.detachSCurveGraph(); } } showDetachButton = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(true, ...(ngDevMode ? [{ debugName: "showDetachButton" }] : [])); // Opt-in: the grid-tile/maximized viewport rendering already has its own dedicated // maximize/minimize control, so this only needs to be enabled where the graph is docked // in the sidebar drawer and has no other way to jump straight to fullscreen. showMaximizeButton = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "showMaximizeButton" }] : [])); // Whether the s-curve view is *currently* the fullscreen maximized panel - flips the // button's icon/tooltip between maximize and minimize, matching the toggle already used // by the dedicated maximize button shown when the graph is a grid/fullscreen viewport. isMaximized = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "isMaximized" }] : [])); toggleMaximize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); points = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const angulations = this.viewportStore.angulations(); const hoveredId = this.hoveredPointId(); // The MPR viewports aren't visible while the s-curve is maximized to fullscreen, so their // live angle dots would be both pointless clutter and misleadingly draggable for views the // user can't see. They come back as soon as the graph leaves fullscreen (minimized or // moved back to the sidebar). const axisPoints = this.isMaximized() ? [] : Object.entries(angulations).map(([key, angulation]) => ({ color: (0,_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.isViewportAxis)(key) ? VIEWPORT_COLORS[key] : 'var(--p-app-graph-label)', hovered: hoveredId === key, id: key, position: [angulation.rl, angulation.cc] })); const chamberPoints = this.renderSettings.sCurveShowChamberPoints() ? this.chamberFacade.chambers().filter(({ hidden }) => !hidden).map(chamber => { const id = chamberPointId(chamber.id); return { color: chamber.color, draggable: false, hovered: hoveredId === id, id, label: chamber.name, position: [chamber.cameraOrientation.rl, chamber.cameraOrientation.cc], snappable: false }; }) : []; const sCurvesById = new Map(this.sCurveFacade.sCurves().map(sCurve => [sCurve.id, sCurve])); const intersectionPoints = this.sCurveFacade.relativeMeasurements().filter(measurement => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.sCurveMeasurementIsIntersection)(measurement)).filter(({ hidden }) => !hidden).map(measurement => { const [a, b] = measurement.sourceIds.map(id => sCurvesById.get(id)); if (!a || !b) return undefined; if (a.hidden || b.hidden) return undefined; const position = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__.getSCurveIntersectionPosition)(a, b); if (!position) return undefined; const id = intersectionPointId(measurement.id); return { color: measurement.color, draggable: false, hovered: hoveredId === id, id, position, snappable: false }; }).filter(point => point !== undefined); // Only the single selected control-point curve's own points render as // draggable, so the graph doesn't show every curve's points at once. const selectedIds = this.sCurveFacade.selectedIds(); if (selectedIds.length !== 1) { return [...axisPoints, ...intersectionPoints, ...chamberPoints]; } const selectedCurve = this.sCurveFacade.sCurves().find(sCurve => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.sCurveIsControlPoint)(sCurve) && sCurve.id === selectedIds[0]); if (!selectedCurve) { return [...axisPoints, ...intersectionPoints, ...chamberPoints]; } const controlPointDots = selectedCurve.controlPoints.map((position, index) => { const id = controlPointId(selectedCurve.id, index); return { color: selectedCurve.color, hovered: hoveredId === id, id, position, snappable: false }; }); return [...axisPoints, ...intersectionPoints, ...chamberPoints, ...controlPointDots]; }, ...(ngDevMode ? [{ debugName: "points" }] : [])); curves = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const sCurves = this.sCurveFacade.sCurves(); const selectedIds = this.sCurveFacade.selectedIds(); const hoveredId = this.hoveredCurveId(); return sCurves.filter(({ hidden }) => !hidden).map(sCurve => ({ color: sCurve.color, curve: sCurve, hovered: sCurve.id === hoveredId, id: sCurve.id, path: (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__.getSCurvePath)(sCurve), selected: selectedIds.includes(sCurve.id) })); }, ...(ngDevMode ? [{ debugName: "curves" }] : [])); handleGraphPointMove(event) { this.renderSettings.lowQualityWithTimeout(); const controlPoint = parseControlPointId(event.pointId); if (controlPoint) { const curve = this.sCurveFacade.sCurves().find(sCurve => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.sCurveIsControlPoint)(sCurve) && sCurve.id === controlPoint.curveId); if (curve) { const controlPoints = curve.controlPoints.map((point, index) => index === controlPoint.index ? event.newPosition : point); this.sCurveFacade.updateSCurve({ controlPoints, id: curve.id }); } return; } if ((0,_tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.isViewportAxis)(event.pointId)) { const [rl, cc] = event.newPosition; if (event.curveId !== undefined) { const curve = this.curves().find(({ id }) => id === event.curveId); if (curve) { const newPosVec = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.angulationToVector)({ ax: 0, cc, rl }); const enFace = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__.getSCurveEnFaceAngle)(curve.curve); const enFaceVec = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.angulationToVector)(enFace); const cross = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(), newPosVec, enFaceVec); // Depending on which point is dragged, we will rotate the angulations // so the proper points are updated in the viewportStore. const rotations = NUM_ROTATIONS[event.pointId]; const angulations = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.rotateArray)([{ ax: 0, cc, rl }, enFace, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_13__.vec3ToPosition)(cross))], rotations); this.viewportStore.updateAngulationsForAllAxes(...angulations); return; } } this.viewportStore.updateAngulationsForAxis({ ax: 0, cc, rl }, event.pointId); } } handlePointSnappedToCurve(event) { // NOTE: When we handle non-spline s-curves, we will need to alter this logic this.annotationFacade.goToAnnotation(event.curveId, true); } handleCurveSelected(event) { if (event.additive) { this.sCurveFacade.toggleSelectSCurve(event.curveId); } else { this.sCurveFacade.selectSCurves([event.curveId]); } } handleMouseDown() { if (!this.interacting()) { const mouseUpHandler = () => { this.interacting.set(false); document.removeEventListener('mouseup', mouseUpHandler); }; document.addEventListener('mouseup', mouseUpHandler); this.interacting.set(true); } } handleCurveContextMenu(event) { const sCurves = this.sCurveFacade.sCurves(); const curve = sCurves.find(({ id }) => id === event.curveId); if (curve) { this.menuItems.set(this.menuItemService.menuItemsForSCurve(curve)); this.contextMenu().show(event.event); } } handleCurveHover(event) { this.hoveredCurveId.set(event.curveId); } handlePointHover(event) { this.hoveredPointId.set(event.pointId); } handleBackgroundClick() { this.sCurveFacade.selectSCurves([]); } handleBackgroundContextMenu({ event }) { this.menuItems.set(this.backgroundMenuItems()); this.contextMenu().show(event); } static ɵfac = function SCurveGraphComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveGraphComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵdefineComponent"]({ type: SCurveGraphComponent, selectors: [["lib-s-curve-graph"]], viewQuery: function SCurveGraphComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵviewQuerySignal"](ctx.contextMenu, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵqueryAdvance"](); } }, inputs: { showDetachButton: [1, "showDetachButton"], showMaximizeButton: [1, "showMaximizeButton"], isMaximized: [1, "isMaximized"] }, outputs: { toggleMaximize: "toggleMaximize" }, decls: 9, vars: 8, consts: [["ctxMenu", ""], ["item", ""], [1, "aspect-square", "overflow-hidden"], [3, "backgroundClicked", "backgroundContextMenu", "pointMoved", "pointSnappedToCurve", "curveContextMenu", "curveHovered", "curveSelected", "pointHovered", "mousedown", "curves", "points", "fontSize", "lineWidth"], [1, "relative", "bottom-[44px]", "flex", "items-center", "justify-end", "gap-1"], ["data-test-id", "s-curve-graph-lib-viewport-button-maximize", "tooltipPosition", "top", "iconType", "prime", 3, "tooltip", "ariaLabel", "icon"], ["tooltipPosition", "top", "data-test-id", "s-curve-graph-p-button-toggle-detach", "size", "small", 3, "icon", "style", "pTooltip", "ariaLabel", "rounded", "text"], [3, "appendTo", "model"], ["data-test-id", "s-curve-graph-lib-viewport-button-maximize", "tooltipPosition", "top", "iconType", "prime", 3, "click", "tooltip", "ariaLabel", "icon"], ["tooltipPosition", "top", "data-test-id", "s-curve-graph-p-button-toggle-detach", "size", "small", 3, "click", "icon", "pTooltip", "ariaLabel", "rounded", "text"], [3, "item"]], template: function SCurveGraphComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "div", 2)(1, "lib-s-curve-graph-base", 3); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("backgroundClicked", function SCurveGraphComponent_Template_lib_s_curve_graph_base_backgroundClicked_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleBackgroundClick()); })("backgroundContextMenu", function SCurveGraphComponent_Template_lib_s_curve_graph_base_backgroundContextMenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleBackgroundContextMenu($event)); })("pointMoved", function SCurveGraphComponent_Template_lib_s_curve_graph_base_pointMoved_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleGraphPointMove($event)); })("pointSnappedToCurve", function SCurveGraphComponent_Template_lib_s_curve_graph_base_pointSnappedToCurve_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handlePointSnappedToCurve($event)); })("curveContextMenu", function SCurveGraphComponent_Template_lib_s_curve_graph_base_curveContextMenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleCurveContextMenu($event)); })("curveHovered", function SCurveGraphComponent_Template_lib_s_curve_graph_base_curveHovered_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleCurveHover($event)); })("curveSelected", function SCurveGraphComponent_Template_lib_s_curve_graph_base_curveSelected_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleCurveSelected($event)); })("pointHovered", function SCurveGraphComponent_Template_lib_s_curve_graph_base_pointHovered_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handlePointHover($event)); })("mousedown", function SCurveGraphComponent_Template_lib_s_curve_graph_base_mousedown_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.handleMouseDown()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](2, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditionalCreate"](3, SCurveGraphComponent_Conditional_3_Template, 3, 7, "lib-viewport-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditionalCreate"](4, SCurveGraphComponent_Conditional_4_Template, 3, 12, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](5, "p-contextmenu", 7, 0); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtemplate"](7, SCurveGraphComponent_ng_template_7_Template, 1, 1, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("curves", ctx.curves())("points", ctx.points())("fontSize", ctx.renderSettings.sCurveGraphFontSize())("lineWidth", ctx.renderSettings.sCurveLineWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditional"](ctx.showMaximizeButton() && !ctx.interacting() ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditional"](ctx.showDetachButton() && !ctx.interacting() ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("appendTo", "body")("model", ctx.menuItems()); } }, dependencies: [_annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_15__.AnnotationMenuItemComponent, primeng_button__WEBPACK_IMPORTED_MODULE_5__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_5__.Button, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_6__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_6__.ContextMenu, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_12__.SCurveGraphBaseComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_7__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_7__.Tooltip, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_12__.ViewportButtonComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 8452 /*!***************************************************************************************************************!*\ !*** ./libs/feature/src/lib/s-curve-relative-measurement-card/s-curve-relative-measurement-card.component.ts ***! \***************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveRelativeMeasurementCardComponent: () => (/* binding */ SCurveRelativeMeasurementCardComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../annotation-menu/directives/annotation-menu-trigger.directive */ 12564); /* harmony import */ var _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../card-theme/card-theme */ 92147); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["nameInput"]; const _c1 = () => ({ color: "var(--p-accordion-header-toggle-icon-color)" }); const _c2 = a0 => ({ secondary: a0 }); const _c3 = a0 => ({ outlined: a0 }); const _c4 = () => ({ root: "py-1 px-0" }); const _forTrack0 = ($index, $item) => $item.icon; function SCurveRelativeMeasurementCardComponent_ng_container_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_4_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](0, SCurveRelativeMeasurementCardComponent_Conditional_4_ng_container_0_Template, 1, 0, "ng-container", 12); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); const dragHandle_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](41); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", dragHandle_r2); } } function SCurveRelativeMeasurementCardComponent_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "lib-icon", 24); } if (rf & 2) { const active_r3 = ctx.active; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵclassMap"](ctx_r3.cn("p-accordionheader-toggle-icon size-(--p-app-icon-size-xxs) text-(length:--p-app-icon-size-xxs)", !ctx_r3.cdkDrag() && "ml-2.5")); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("icon", active_r3 ? "chevron-down" : "chevron-right"); } } function SCurveRelativeMeasurementCardComponent_ng_container_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "input", 25, 7); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("click", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keydown.space", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keydown_space_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keyup.space", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keyup_space_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("keydown.enter", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keydown_enter_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation()($event)); })("keyup.enter", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keyup_enter_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.commitEditName)($event)); })("keydown.escape", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keydown_escape_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation()($event)); })("keyup.escape", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_keyup_escape_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.cancelEditName)($event)); })("blur", function SCurveRelativeMeasurementCardComponent_Conditional_11_Template_input_blur_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.commitEditName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("formControl", ctx_r3.measurementName); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵattribute"]("data-test-id", "s-curve-relative-measurement-card-input-" + ctx_r3.measurement().id + "-name")("maxlength", ctx_r3.nameMaxLength)("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](2, 4, "common.name")); } } function SCurveRelativeMeasurementCardComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "button", 26); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("click", function SCurveRelativeMeasurementCardComponent_Conditional_12_Template_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.handleNameEventPropagation(ctx_r3.onEditName)($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](1, "span", 27); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵattribute"]("data-test-id", "s-curve-relative-measurement-card-button-" + ctx_r3.measurement().id + "-name-trigger"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate"](ctx_r3.measurement().name); } } function SCurveRelativeMeasurementCardComponent_Conditional_13_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](0, SCurveRelativeMeasurementCardComponent_Conditional_13_ng_container_0_Template, 1, 0, "ng-container", 12); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); const visibilityBtn_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](45); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", visibilityBtn_r7); } } function SCurveRelativeMeasurementCardComponent_Conditional_14_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](0, SCurveRelativeMeasurementCardComponent_Conditional_14_ng_container_0_Template, 1, 0, "ng-container", 12); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); const moreMenuBtn_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](47); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", moreMenuBtn_r8); } } function SCurveRelativeMeasurementCardComponent_ng_container_16_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_Conditional_31_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "div", 21)(1, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](4, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"]("", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](3, 2, "annotationMenu.position"), ":"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", ctx_r3.positionText() ?? "\u2014", " "); } } function SCurveRelativeMeasurementCardComponent_ng_container_39_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementContainer"](0); } } function SCurveRelativeMeasurementCardComponent_ng_template_40_div_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "div", 30); } } function SCurveRelativeMeasurementCardComponent_ng_template_40_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "lib-icon", 28); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](2, SCurveRelativeMeasurementCardComponent_ng_template_40_div_2_Template, 1, 0, "div", 29); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵattribute"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](1, 1, "annotationCard.dragToReorder")); } } function SCurveRelativeMeasurementCardComponent_ng_template_42_Template(rf, ctx) { if (rf & 1) { const _r9 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "div", 31); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("dblclick", function SCurveRelativeMeasurementCardComponent_ng_template_42_Template_div_dblclick_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r9); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.goTo.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](1, "lib-icon", 32); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵclassMap"](ctx_r3.cn("bg-surface-900 flex size-7.5 shrink-0 items-center justify-center rounded-full", ctx_r3.measurement().hidden && "opacity-80")); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵstyleProp"]("color", ctx_r3.accentColor()); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("icon", ctx_r3.isIntersection() ? "point" : "angle"); } } function SCurveRelativeMeasurementCardComponent_ng_template_44_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "lib-icon", 34); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("icon", ctx_r3.measurement().hidden ? "eye" : "eye-off"); } } function SCurveRelativeMeasurementCardComponent_ng_template_44_Template(rf, ctx) { if (rf & 1) { const _r10 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "p-button", 33); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("click", function SCurveRelativeMeasurementCardComponent_ng_template_44_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r10); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r3.measurement().hidden ? ctx_r3.show.emit() : ctx_r3.hide.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](2, SCurveRelativeMeasurementCardComponent_ng_template_44_ng_template_2_Template, 1, 1, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction1"](7, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction1"](5, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction0"](4, _c1))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](1, 2, ctx_r3.measurement().hidden ? "common.show" : "common.hide")); } } function SCurveRelativeMeasurementCardComponent_ng_template_46_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "lib-icon", 36); } } function SCurveRelativeMeasurementCardComponent_ng_template_46_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "p-button", 35); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](2, SCurveRelativeMeasurementCardComponent_ng_template_46_ng_template_2_Template, 1, 0, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction1"](9, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction1"](7, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction0"](6, _c1))))("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](1, 4, "common.moreActions"))("libMenuTrigger", ctx_r3.menuTrigger())("libMenuActions", ctx_r3.actions()); } } function SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Conditional_0_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "lib-icon", 40); } if (rf & 2) { const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("icon", action_r12.icon)("pTooltip", action_r12.label); } } function SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r11 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "p-button", 39); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("click", function SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Conditional_0_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r11); const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"]().$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](action_r12.command == null ? null : action_r12.command($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](1, SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Conditional_0_ng_template_1_Template, 1, 2, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const action_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpureFunction0"](2, _c4))("disabled", action_r12.disabled); } } function SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](0, SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Conditional_0_Template, 3, 3, "p-button", 38); } if (rf & 2) { const action_r12 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](action_r12.icon ? 0 : -1); } } function SCurveRelativeMeasurementCardComponent_ng_template_48_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "div", 37); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵrepeaterCreate"](1, SCurveRelativeMeasurementCardComponent_ng_template_48_For_2_Template, 1, 1, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵrepeater"](ctx_r3.cardActions()); } } function SCurveRelativeMeasurementCardComponent_ng_template_50_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](0, "div", 41); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵstyleProp"]("background-color", ctx_r3.selected() ? ctx_r3.accentColor() : ""); } } class SCurveRelativeMeasurementCardComponent { actions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)([], ...(ngDevMode ? [{ debugName: "actions" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); measurement = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "measurement" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "selected" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); menuTrigger = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(...(ngDevMode ? [undefined, { debugName: "menuTrigger" }] : [])); cdkDrag = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(false, { ...(ngDevMode ? { debugName: "cdkDrag" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_2__.booleanAttribute }); sCurveFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_14__.SCurveFacade); show = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); hide = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); goTo = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); clicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); updateName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); cancelClick = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_15__.CancelClickDirective, ...(ngDevMode ? [{ debugName: "cancelClick" }] : [])); nameInput = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('nameInput', ...(ngDevMode ? [{ debugName: "nameInput" }] : [])); isEditingName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isEditingName" }] : [])); measurementName = new _angular_forms__WEBPACK_IMPORTED_MODULE_5__.FormControl(''); nameMaxLength = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_16__.ANNOTATION_NAME_MAX_LENGTH; ngAfterViewInit() { this.cancelClick()?.filteredClick.subscribe(event => this.clicked.emit(event)); } mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.buildCardPt)(this.pt(), this.cardState()), ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); dt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.buildCardDt)(_card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.DARK_CARD_THEME[this.cardState()]), ...(ngDevMode ? [{ debugName: "dt" }] : [])); accentColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.measurement().hidden ? 'var(--p-text-muted-color)' : this.measurement().color, ...(ngDevMode ? [{ debugName: "accentColor" }] : [])); cardActions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.actions().filter(action => action.includeInCard), ...(ngDevMode ? [{ debugName: "cardActions" }] : [])); isIntersection = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_11__.sCurveMeasurementIsIntersection)(this.measurement()), ...(ngDevMode ? [{ debugName: "isIntersection" }] : [])); cardButtonStyle = _card_theme_card_theme__WEBPACK_IMPORTED_MODULE_18__.CARD_BUTTON_STYLE; cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_16__.cn; cardState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { if (this.measurement().hidden) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.CardState.DISABLED; if (this.selected()) return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.CardState.SELECTED; return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.CardState.DEFAULT; }, ...(ngDevMode ? [{ debugName: "cardState" }] : [])); sources = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const sourcesById = new Map(this.sCurveFacade.sCurves().map(sCurve => [sCurve.id, sCurve])); const [a, b] = this.measurement().sourceIds.map(id => sourcesById.get(id)); return a && b ? [a, b] : undefined; }, ...(ngDevMode ? [{ debugName: "sources" }] : [])); angleDegrees = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const sources = this.sources(); return sources ? (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.getSCurveAngleDegrees)(sources[0], sources[1]) : undefined; }, ...(ngDevMode ? [{ debugName: "angleDegrees" }] : [])); sourceNames = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const sources = this.sources(); return sources ? [sources[0].name, sources[1].name] : undefined; }, ...(ngDevMode ? [{ debugName: "sourceNames" }] : [])); positionText = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const sources = this.sources(); if (!sources) return; const angulation = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.getSCurveIntersectionAngulation)(sources[0], sources[1]); if (!angulation) return; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_16__.formatAngulationtxt)(angulation, false); }, ...(ngDevMode ? [{ debugName: "positionText" }] : [])); contextMenu(event) { if (event.ctrlKey) { event.preventDefault(); this.clicked.emit(event); return; } const trigger = this.menuTrigger(); if (!trigger) return; trigger.model.set(this.actions()); trigger.toggle(event); } onEditName = () => { if (this.isEditingName()) return; this.measurementName.setValue(this.measurement().name); this.menuTrigger()?.hide(); this.isEditingName.set(true); setTimeout(() => this.nameInput()?.nativeElement.focus()); }; cancelEditName = () => { this.isEditingName.set(false); }; commitEditName = () => { const value = this.measurementName.value ?? ''; if (value.trim().length === 0) { this.cancelEditName(); return; } this.isEditingName.set(false); this.updateName.emit(value.trim()); }; handleNameEventPropagation(callback) { return event => { event.stopPropagation(); event.preventDefault(); callback?.(); }; } static ɵfac = function SCurveRelativeMeasurementCardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveRelativeMeasurementCardComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵdefineComponent"]({ type: SCurveRelativeMeasurementCardComponent, selectors: [["lib-s-curve-relative-measurement-card"]], viewQuery: function SCurveRelativeMeasurementCardComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵviewQuerySignal"](ctx.cancelClick, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_15__.CancelClickDirective, 5)(ctx.nameInput, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵqueryAdvance"](2); } }, inputs: { actions: [1, "actions"], pt: [1, "pt"], measurement: [1, "measurement"], selected: [1, "selected"], menuTrigger: [1, "menuTrigger"], cdkDrag: [1, "cdkDrag"] }, outputs: { show: "show", hide: "hide", goTo: "goTo", clicked: "clicked", updateName: "updateName" }, decls: 52, vars: 33, consts: [["toggleicon", ""], ["dragHandle", ""], ["cardIcon", ""], ["visibilityBtn", ""], ["moreMenuBtn", ""], ["contentActions", ""], ["accentBar", ""], ["nameInput", ""], ["icon", ""], [3, "click", "contextmenu"], [1, "grow", 3, "pt", "dt", "value"], ["libCancelClick", "", 1, "relative", 3, "pt"], [4, "ngTemplateOutlet"], [1, "order-last", "flex", "w-full", "min-w-0", "items-center", "justify-between", "gap-1"], [1, "flex", "w-full", "min-w-0", "grow", "items-center", "gap-3", "py-0.5"], [1, "flex", "min-w-0", "grow", "items-center", "justify-between", "text-sm"], ["pInputText", "", "data-propagate-click", "", 1, "border-primary-400", "bg-transparent", "py-0.5", "text-sm", "text-inherit", 3, "formControl"], ["type", "button", "data-propagate-click", "", 1, "min-w-0", "flex-1", "cursor-pointer", "text-left"], [1, "relative", 3, "pt"], [1, "flex", "gap-3"], [1, "flex", "grow", "flex-col", "gap-1", "py-1", "text-xs"], [1, "flex", "gap-1"], [1, "text-color", "font-bold"], [1, "flex", "grow", "justify-end", "text-(--p-accordion-content-muted-color)"], ["data-propagate-click", "", 3, "icon"], ["pInputText", "", "data-propagate-click", "", 1, "border-primary-400", "bg-transparent", "py-0.5", "text-sm", "text-inherit", 3, "click", "keydown.space", "keyup.space", "keydown.enter", "keyup.enter", "keydown.escape", "keyup.escape", "blur", "formControl"], ["type", "button", "data-propagate-click", "", 1, "min-w-0", "flex-1", "cursor-pointer", "text-left", 3, "click"], [1, "line-clamp-2", "wrap-anywhere"], ["cdkDragHandle", "", "icon", "drag-handle", 1, "order-first", "size-3", "cursor-grab", "px-1.5", "py-3", "text-(--p-accordion-header-toggle-icon-hover-color)", "opacity-0", "transition-opacity", "delay-100", "group-hover:opacity-100", "active:cursor-grabbing"], ["class", "h-11 rounded-sm bg-(--p-app-dark-surface-base)", 4, "cdkDragPlaceholder"], [1, "h-11", "rounded-sm", "bg-(--p-app-dark-surface-base)"], [3, "dblclick"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"], ["data-test-id", "s-curve-relative-measurement-card-p-button-visibility", "data-propagate-click", "", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "dt", "pTooltip"], [1, "size-(--p-app-icon-size-xs)", 3, "icon"], ["data-test-id", "s-curve-relative-measurement-card-p-button-more-actions", "data-propagate-click", "", "severity", "secondary", "outlined", "", "size", "small", 3, "dt", "pTooltip", "libMenuTrigger", "libMenuActions"], ["icon", "ellipsis-v", 1, "size-(--p-app-icon-size-xxxs)", "text-(length:--p-app-icon-size-xxxs)"], [1, "flex", "flex-col", "items-center"], ["data-test-id", "s-curve-relative-measurement-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "pt", "disabled"], ["data-test-id", "s-curve-relative-measurement-card-p-button-action", "severity", "secondary", "outlined", "", "size", "small", 3, "click", "pt", "disabled"], [1, "size-(--p-app-icon-size-sm)", 3, "icon", "pTooltip"], [1, "absolute", "top-0", "left-0", "h-full", "w-1"]], template: function SCurveRelativeMeasurementCardComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("click", function SCurveRelativeMeasurementCardComponent_Template_div_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.clicked.emit($event)); })("contextmenu", function SCurveRelativeMeasurementCardComponent_Template_div_contextmenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx.contextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](1, "p-accordion-panel", 10)(2, "p-accordion-header", 11); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](3, SCurveRelativeMeasurementCardComponent_ng_container_3_Template, 1, 0, "ng-container", 12); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](4, SCurveRelativeMeasurementCardComponent_Conditional_4_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](5, SCurveRelativeMeasurementCardComponent_ng_template_5_Template, 1, 3, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](7, "div", 13)(8, "div", 14); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](9, SCurveRelativeMeasurementCardComponent_ng_container_9_Template, 1, 0, "ng-container", 12); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](10, "div", 15); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](11, SCurveRelativeMeasurementCardComponent_Conditional_11_Template, 3, 6, "input", 16)(12, SCurveRelativeMeasurementCardComponent_Conditional_12_Template, 3, 2, "button", 17); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](13, SCurveRelativeMeasurementCardComponent_Conditional_13_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](14, SCurveRelativeMeasurementCardComponent_Conditional_14_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](15, "p-accordion-content", 18); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](16, SCurveRelativeMeasurementCardComponent_ng_container_16_Template, 1, 0, "ng-container", 12); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](17, "div", 19)(18, "div", 20)(19, "div", 21)(20, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](21); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](22, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](23, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](24); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](25, "div", 21)(26, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](27); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](28, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](29, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](30); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditionalCreate"](31, SCurveRelativeMeasurementCardComponent_Conditional_31_Template, 6, 4, "div", 21); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](32, "div", 21)(33, "span", 22); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](34); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](35, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](36, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtext"](37); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipe"](38, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](39, SCurveRelativeMeasurementCardComponent_ng_container_39_Template, 1, 0, "ng-container", 12); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplate"](40, SCurveRelativeMeasurementCardComponent_ng_template_40_Template, 3, 3, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"])(42, SCurveRelativeMeasurementCardComponent_ng_template_42_Template, 2, 5, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"])(44, SCurveRelativeMeasurementCardComponent_ng_template_44_Template, 4, 9, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"])(46, SCurveRelativeMeasurementCardComponent_ng_template_46_Template, 4, 11, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"])(48, SCurveRelativeMeasurementCardComponent_ng_template_48_Template, 3, 0, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"])(50, SCurveRelativeMeasurementCardComponent_ng_template_50_Template, 1, 2, "ng-template", null, 6, _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { let tmp_22_0; let tmp_24_0; const cardIcon_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](43); const contentActions_r14 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](49); const accentBar_r15 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵreference"](51); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵclassMap"](ctx.cn("group flex w-full overflow-hidden border-b border-(--p-app-border-subtle)", ctx.mergedPt().wrapper)); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵstyleMap"](ctx.cardButtonStyle); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("pt", ctx.mergedPt().panel)("dt", ctx.dt())("value", ctx.measurement().id); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("pt", ctx.mergedPt().header); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r15); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](ctx.cdkDrag() ? 4 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", cardIcon_r13); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](ctx.isEditingName() ? 11 : 12); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](!ctx.isEditingName() ? 13 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](ctx.menuTrigger() && ctx.actions().length && !ctx.isEditingName() ? 14 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("pt", ctx.mergedPt().content); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", accentBar_r15); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](22, 24, "annotationMenu.sCurveRelativeMeasurements.sCurve1"), ": "); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", ((tmp_22_0 = ctx.sourceNames()) == null ? null : tmp_22_0[0]) ?? "\u2014", " "); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](28, 26, "annotationMenu.sCurveRelativeMeasurements.sCurve2"), ": "); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", ((tmp_24_0 = ctx.sourceNames()) == null ? null : tmp_24_0[1]) ?? "\u2014", " "); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵconditional"](ctx.isIntersection() ? 31 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"]("", _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind1"](35, 28, "annotationMenu.angle"), ":"); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵtextInterpolate1"](" ", ctx.angleDegrees() !== undefined ? _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵpipeBind2"](38, 30, ctx.angleDegrees(), "1.0-1") + "\u00B0" : "\u2014", " "); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("ngTemplateOutlet", contentActions_r14); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_7__.AccordionContent, primeng_accordion__WEBPACK_IMPORTED_MODULE_7__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_7__.AccordionPanel, _annotation_menu_directives_annotation_menu_trigger_directive__WEBPACK_IMPORTED_MODULE_17__.AnnotationMenuTriggerDirective, primeng_button__WEBPACK_IMPORTED_MODULE_8__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_15__.CancelClickDirective, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragHandle, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDragPlaceholder, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.NgControlStatus, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_15__.IconComponent, primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_9__.InputText, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_5__.FormControlDirective, primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__.Tooltip, _angular_common__WEBPACK_IMPORTED_MODULE_1__.DecimalPipe, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_6__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 17464 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/s-curve-relative-measurements/s-curve-relative-measurements.service.ts ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveRelativeMeasurementsService: () => (/* binding */ SCurveRelativeMeasurementsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../colors/colors.service */ 39298); class SCurveRelativeMeasurementsService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.AnnotationFacade); sCurveFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.SCurveFacade); colorsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_6__.ColorsService); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore); createAngle(a, b) { const measurement = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.sCurveAngleMeasurement)({ color: this.nextColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.incrementName)('Angle', this.measurementNames(), _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.ANNOTATION_NAME_MAX_LENGTH), sourceIds: [a.id, b.id] }); this.sCurveFacade.addRelativeMeasurement(measurement); } createIntersection(a, b) { const measurement = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.sCurveIntersectionMeasurement)({ color: this.nextColor(), hidden: false, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.incrementName)('Intersection', this.measurementNames(), _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.ANNOTATION_NAME_MAX_LENGTH), sourceIds: [a.id, b.id] }); this.sCurveFacade.addRelativeMeasurement(measurement); } // Rotates the viewports to the angulation where the two source curves cross. // That view has both source planes edge-on, and is also the projection in // which the angle between them appears at true size — so it serves both // measurement types. goTo(measurement) { const sources = this.resolveSources(measurement); if (!sources) return; const angulation = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__.getSCurveIntersectionAngulation)(...sources); if (!angulation) return; // Center on a spline source's annotation when one exists; control-point // curves have no backing annotation. const splineSource = sources.find(source => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.sCurveIsSpline)(source)); if (splineSource) this.annotationFacade.goToAnnotation(splineSource.id, true); const enFace = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__.getSCurveEnFaceAngle)(sources[0]); const cross = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.angulationToVector)(angulation), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.angulationToVector)(enFace)); this.viewportStore.updateAngulationsForAllAxes(angulation, enFace, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vec3ToPosition)(cross))); } hasGoToTarget(measurement) { const sources = this.resolveSources(measurement); return !!sources && !!(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__.getSCurveIntersectionAngulation)(...sources); } resolveSources(measurement) { const sourcesById = new Map(this.sCurveFacade.sCurves().map(sCurve => [sCurve.id, sCurve])); const [a, b] = measurement.sourceIds.map(id => sourcesById.get(id)); return a && b ? [a, b] : undefined; } nextColor() { const usedColors = new Set([...this.sCurveFacade.relativeMeasurements().map(({ color }) => color), ...this.sCurveFacade.sCurves().map(({ color }) => color)]); const available = this.colorsService.colors.find(color => !usedColors.has(color)); return available ?? this.colorsService.currentColor(); } measurementNames() { return this.sCurveFacade.relativeMeasurements().map(({ name }) => name); } static ɵfac = function SCurveRelativeMeasurementsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveRelativeMeasurementsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: SCurveRelativeMeasurementsService, factory: SCurveRelativeMeasurementsService.ɵfac }); } /***/ }, /***/ 9610 /*!****************************************************************************!*\ !*** ./libs/feature/src/lib/services/submenu-flip/submenu-flip.service.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SubmenuFlipService: () => (/* binding */ SubmenuFlipService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); const CONTEXT_MENU_SUB = 'p-contextmenu-sub'; const SUBMENU_LIST_SELECTOR = 'ul.p-contextmenu-submenu'; const BOTTOM_MARGIN = 8; const CONTEXT_MENU_ITEM_ACTIVE = 'p-contextmenu-item-active'; class SubmenuFlipService { observer; positioningSubmenus = new WeakSet(); start(root = document.body) { this.stop(); this.observer = new MutationObserver(mutations => { for (const mutation of mutations) { this.handleAddedNodes(mutation); this.handleClassChange(mutation); } }); this.observer.observe(root, { attributeFilter: ['class'], attributes: true, childList: true, subtree: true }); } stop() { this.observer?.disconnect(); this.observer = undefined; } ngOnDestroy() { this.stop(); } handleAddedNodes(mutation) { for (const node of mutation.addedNodes) { if (!(node instanceof HTMLElement)) continue; if (node.tagName?.toLowerCase() === CONTEXT_MENU_SUB) { this.positionSubmenu(node); } const nestedSubmenus = node.querySelectorAll?.(CONTEXT_MENU_SUB) ?? []; for (const element of nestedSubmenus) { this.positionSubmenu(element); } } } handleClassChange(mutation) { if (mutation.type !== 'attributes' || mutation.attributeName !== 'class') return; const target = mutation.target; const isActive = target.classList.contains(CONTEXT_MENU_ITEM_ACTIVE); if (!isActive) return; const submenu = target.querySelector(`:scope > ${CONTEXT_MENU_SUB}`); if (submenu) this.positionSubmenu(submenu); } positionSubmenu(hostElement) { const submenu = hostElement.querySelector(SUBMENU_LIST_SELECTOR) ?? hostElement.closest(`${CONTEXT_MENU_SUB}`)?.querySelector(SUBMENU_LIST_SELECTOR) ?? hostElement; if (this.positioningSubmenus.has(submenu)) return; this.positioningSubmenus.add(submenu); requestAnimationFrame(() => { this.positioningSubmenus.delete(submenu); const previousTransform = submenu.style.transform; submenu.style.transform = ''; const rect = submenu.getBoundingClientRect(); const overflow = rect.bottom - (window.innerHeight - BOTTOM_MARGIN); if (overflow > 0) { submenu.style.setProperty('transform', `translateY(-${overflow}px)`, 'important'); } if (previousTransform) { submenu.style.transform = previousTransform; } }); } static ɵfac = function SubmenuFlipService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SubmenuFlipService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: SubmenuFlipService, factory: SubmenuFlipService.ɵfac }); } /***/ }, /***/ 3879 /*!********************************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/annotation-panel/annotation-panel.component.ts ***! \********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationPanelComponent: () => (/* binding */ AnnotationPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_message__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/message */ 60134); /* harmony import */ var primeng_tag__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/tag */ 37587); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../annotation-card/annotation-card.component */ 86628); /* harmony import */ var _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _work_session_work_session_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../work-session/work-session.service */ 82757); /* harmony import */ var _services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../services/annotation-panel.service */ 56105); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({}); const _c1 = () => []; const _c2 = () => ({ root: "flex h-[18px] items-center rounded-sm bg-(--p-app-phase-active-item-background)! px-2 text-[10px] leading-none font-normal text-(--p-app-neutral-400)!" }); const _c3 = () => ({ content: "pt-2 pb-4 ml-12" }); const _c4 = () => ({ root: "min-h-11 gap-2 py-0 pl-1.5 text-sm font-normal" }); const _c5 = (a0, a1) => ({ content: a0, header: a1 }); const _forTrack0 = ($index, $item) => $item.phaseId; const _forTrack1 = ($index, $item) => $item.annotation.id; function AnnotationPanelComponent_Conditional_2_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "lib-icon", 4); } } function AnnotationPanelComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "p-message", 2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtemplate"](1, AnnotationPanelComponent_Conditional_2_ng_template_1_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](3, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](4, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipeBind1"](5, 2, "volumeViewer.drawer.content.noAnnotationsFound")); } } function AnnotationPanelComponent_Conditional_3_For_2_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "p-tag", 9); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("value", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipeBind1"](1, 2, "multiphase.inFocus"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](4, _c2)); } } function AnnotationPanelComponent_Conditional_3_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div")(1, "span", 8); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](3, AnnotationPanelComponent_Conditional_3_For_2_Conditional_1_Conditional_3_Template, 2, 5, "p-tag", 9); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("flex h-[32px] items-center justify-between gap-2 px-3 text-xs font-normal uppercase", group_r4.isActive ? "bg-(--p-app-phase-active-background) text-(--p-app-phase-active-color)" : "text-(--p-app-neutral-500)")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtextInterpolate"](group_r4.headerLabel); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](group_r4.isActive ? 3 : -1); } } function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "lib-annotation-card", 10); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("show", function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template_lib_annotation_card_show_0_listener() { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.onShowAnnotation(item_r6.annotation.id)); })("hide", function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template_lib_annotation_card_hide_0_listener() { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.onHideAnnotation(item_r6.annotation.id)); })("updateName", function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template_lib_annotation_card_updateName_0_listener($event) { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.onUpdateAnnotationName($event, item_r6.annotation.id)); })("goTo", function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template_lib_annotation_card_goTo_0_listener() { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.panel.onGoToAnnotation(item_r6.annotation.id) : ctx_r1.revealInPhase(group_r4.phaseId, item_r6.annotation.id)); })("clicked", function AnnotationPanelComponent_Conditional_3_For_2_For_4_Template_lib_annotation_card_clicked_0_listener($event) { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.panel.handleAnnotationCardClick($event, item_r6.annotation.id) : ctx_r1.revealInPhase(group_r4.phaseId, item_r6.annotation.id)); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const item_r6 = ctx.$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); const moreActionsMenu_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("cdkDragDisabled", !group_r4.isActive)("readOnly", !group_r4.isActive)("annotation", item_r6.annotation)("actions", item_r6.moreActions)("selected", item_r6.selected)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction2"](9, _c5, _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](7, _c3), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](8, _c4)))("menuTrigger", moreActionsMenu_r7); } } function AnnotationPanelComponent_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](1, AnnotationPanelComponent_Conditional_3_For_2_Conditional_1_Template, 4, 4, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](2, "p-accordion", 6); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("cdkDropListDropped", function AnnotationPanelComponent_Conditional_3_For_2_Template_p_accordion_cdkDropListDropped_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.handleAnnotationDrop($event)); })("valueChange", function AnnotationPanelComponent_Conditional_3_For_2_Template_p_accordion_valueChange_2_listener($event) { const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.onAccordionValueChange($event) : ctx_r1.expandOnSwitch(group_r4, $event)); })("click", function AnnotationPanelComponent_Conditional_3_For_2_Template_p_accordion_click_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeaterCreate"](3, AnnotationPanelComponent_Conditional_3_For_2_For_4_Template, 1, 12, "lib-annotation-card", 7, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"]()(); } if (rf & 2) { const group_r4 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn(ctx_r1.showPhaseLabels() && "overflow-hidden rounded-md bg-(--p-app-surface-card)")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](ctx_r1.showPhaseLabels() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("block", !group_r4.isActive && "opacity-50")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("multiple", true)("cdkDropListDisabled", !group_r4.isActive)("value", group_r4.isActive ? ctx_r1.expandedDrawerPanelIds() : _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](8, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeater"](group_r4.cards); } } function AnnotationPanelComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("click", function AnnotationPanelComponent_Conditional_3_Template_div_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.deselectAnnotations()); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeaterCreate"](1, AnnotationPanelComponent_Conditional_3_For_2_Template, 5, 9, "div", 3, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("min-h-full", ctx_r1.showPhaseLabels() && "flex flex-col gap-2.5 px-[9px] py-2")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeater"](ctx_r1.displayGroups()); } } class AnnotationPanelComponent { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.AnnotationFacade); panel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_14__.AnnotationPanelService); workSessionService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_work_session_work_session_service__WEBPACK_IMPORTED_MODULE_13__.WorkSessionService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateService); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.cn; expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); focusedPhaseId; pendingExpandId; annotations = this.panel.annotations; langChange = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)(this.translate.onLangChange); groups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this.langChange(); const groups = this.workSessionService.annotationGroups(); const gated = groups.some(group => group.identification !== undefined); const word = this.translate.instant(gated ? 'multiphase.phase' : 'multiphase.volume'); const triggerUnit = this.translate.instant('multiphase.triggerUnit'); return groups.map(group => { const detail = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.formatPhaseIdentification)(group.identification, { triggerUnit }); const base = `${word} ${group.label}`; return { ...group, headerLabel: detail ? `${base}: ${detail}` : base }; }); }, ...(ngDevMode ? [{ debugName: "groups" }] : [])); nonEmptyGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.groups().filter(group => group.annotations.length > 0), ...(ngDevMode ? [{ debugName: "nonEmptyGroups" }] : [])); displayGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().map(group => { const cards = group.isActive ? this.annotations() : group.annotations.map(annotation => ({ annotation: { ...annotation, measurements: [] }, contentMenuItems: [], moreActions: [], selected: false })); return { ...group, cards }; }), ...(ngDevMode ? [{ debugName: "displayGroups" }] : [])); hasAnyAnnotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().length > 0, ...(ngDevMode ? [{ debugName: "hasAnyAnnotations" }] : [])); // A single-phase (or single-volume) series has nothing to disambiguate - the phase // header only earns its place once there's more than one group to tell apart. showPhaseLabels = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().length > 1, ...(ngDevMode ? [{ debugName: "showPhaseLabels" }] : [])); constructor() { // Reset expand state on every phase switch, except the card whose chevron triggered it. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const groups = this.nonEmptyGroups(); const focusedPhaseId = groups.find(group => group.isActive)?.phaseId; if (focusedPhaseId === this.focusedPhaseId) return; this.focusedPhaseId = focusedPhaseId; const pending = this.pendingExpandId; this.pendingExpandId = undefined; const expandPending = pending !== undefined && groups.some(group => group.isActive && group.annotations.some(({ id }) => id === pending)); this.expandedDrawerPanelIds.set(expandPending ? [pending] : []); }); } revealInPhase(phaseId, annotationId) { this.workSessionService.requestActiveVolume(phaseId, annotationId); } expandOnSwitch(group, value) { const id = (Array.isArray(value) ? value : []).at(-1); if (id === undefined) return; this.pendingExpandId = id; this.workSessionService.requestActiveVolume(group.phaseId, id); } onAccordionValueChange(value) { this.expandedDrawerPanelIds.set(Array.isArray(value) ? value : []); } handleAnnotationDrop(event) { const currentAnnotations = [...this.annotationFacade.annotations()]; (0,_angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.moveItemInArray)(currentAnnotations, event.previousIndex, event.currentIndex); this.annotationFacade.loadAnnotations(currentAnnotations); } static ɵfac = function AnnotationPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineComponent"]({ type: AnnotationPanelComponent, selectors: [["lib-annotation-panel"]], hostAttrs: [1, "block", "h-full", "overflow-y-auto"], decls: 4, vars: 1, consts: [["moreActionsMenu", ""], ["icon", ""], ["severity", "secondary", "variant", "simple", 1, "p-4", 3, "pt"], [3, "class"], ["icon", "info-circle"], [3, "click"], ["cdkDropList", "", 3, "cdkDropListDropped", "valueChange", "click", "multiple", "cdkDropListDisabled", "value"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "cdkDragDisabled", "readOnly", "annotation", "actions", "selected", "pt", "menuTrigger"], [1, "min-w-0", "truncate"], [3, "value", "pt"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "show", "hide", "updateName", "goTo", "clicked", "cdkDragDisabled", "readOnly", "annotation", "actions", "selected", "pt", "menuTrigger"]], template: function AnnotationPanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "lib-annotation-menu", null, 0); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](2, AnnotationPanelComponent_Conditional_2_Template, 6, 5, "p-message", 2)(3, AnnotationPanelComponent_Conditional_3_Template, 3, 2, "div", 3); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](!ctx.hasAnyAnnotations() ? 2 : 3); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_5__.Accordion, _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_11__.AnnotationCardComponent, _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_12__.AnnotationMenuComponent, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDropList, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDrag, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.IconComponent, primeng_message__WEBPACK_IMPORTED_MODULE_6__.Message, primeng_tag__WEBPACK_IMPORTED_MODULE_7__.Tag, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 40737 /*!**************************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/chamber-panel/chamber-panel.component.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberPanelComponent: () => (/* binding */ ChamberPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_message__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/message */ 60134); /* harmony import */ var primeng_tag__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/tag */ 37587); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _chamber_chamber_card_chamber_card_component__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../chamber/chamber-card/chamber-card.component */ 69605); /* harmony import */ var _chamber_chamber_menu_components_chamber_menu_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../chamber/chamber-menu/components/chamber-menu.component */ 23204); /* harmony import */ var _work_session_work_session_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../work-session/work-session.service */ 82757); /* harmony import */ var _services_chamber_panel_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../services/chamber-panel.service */ 38164); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({}); const _c1 = () => []; const _c2 = () => ({ root: "flex h-[18px] items-center rounded-sm bg-(--p-app-phase-active-item-background)! px-2 text-[10px] leading-none font-normal text-(--p-app-neutral-400)!" }); const _c3 = () => ({ content: "pt-2 pb-4 ml-12" }); const _c4 = () => ({ root: "min-h-11 gap-2 py-0 pl-1.5 text-sm font-normal" }); const _c5 = (a0, a1) => ({ content: a0, header: a1 }); const _forTrack0 = ($index, $item) => $item.phaseId; const _forTrack1 = ($index, $item) => $item.chamber.id; function ChamberPanelComponent_Conditional_2_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "lib-icon", 4); } } function ChamberPanelComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "p-message", 2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtemplate"](1, ChamberPanelComponent_Conditional_2_ng_template_1_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](3, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](4, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipeBind1"](5, 2, "volumeViewer.drawer.content.noChambersFound")); } } function ChamberPanelComponent_Conditional_3_For_2_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "p-tag", 9); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipe"](1, "translate"); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("value", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpipeBind1"](1, 2, "multiphase.inFocus"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](4, _c2)); } } function ChamberPanelComponent_Conditional_3_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div")(1, "span", 8); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](3, ChamberPanelComponent_Conditional_3_For_2_Conditional_1_Conditional_3_Template, 2, 5, "p-tag", 9); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("flex h-[32px] items-center justify-between gap-2 px-3 text-xs font-normal uppercase", group_r4.isActive ? "bg-(--p-app-phase-active-background) text-(--p-app-phase-active-color)" : "text-(--p-app-neutral-500)")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵtextInterpolate"](group_r4.headerLabel); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](group_r4.isActive ? 3 : -1); } } function ChamberPanelComponent_Conditional_3_For_2_For_4_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "lib-chamber-card", 10); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("clicked", function ChamberPanelComponent_Conditional_3_For_2_For_4_Template_lib_chamber_card_clicked_0_listener($event) { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.panel.handleChamberCardClick($event, item_r6.chamber.id) : ctx_r1.revealInPhase(group_r4.phaseId, item_r6.chamber.id)); })("updateName", function ChamberPanelComponent_Conditional_3_For_2_For_4_Template_lib_chamber_card_updateName_0_listener($event) { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.onUpdateChamberName($event, item_r6.chamber.id)); })("goTo", function ChamberPanelComponent_Conditional_3_For_2_For_4_Template_lib_chamber_card_goTo_0_listener() { const item_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.panel.onGoToChamber(item_r6.chamber) : ctx_r1.revealInPhase(group_r4.phaseId, item_r6.chamber.id)); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const item_r6 = ctx.$implicit; const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); const moreActionsMenu_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("cdkDragDisabled", !group_r4.isActive)("readOnly", !group_r4.isActive)("chamber", item_r6.chamber)("actions", item_r6.moreActions)("selected", item_r6.selected)("menuTrigger", moreActionsMenu_r7)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction2"](9, _c5, _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](7, _c3), _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](8, _c4))); } } function ChamberPanelComponent_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](1, ChamberPanelComponent_Conditional_3_For_2_Conditional_1_Template, 4, 4, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](2, "p-accordion", 6); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("cdkDropListDropped", function ChamberPanelComponent_Conditional_3_For_2_Template_p_accordion_cdkDropListDropped_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.handleAnnotationDrop($event)); })("valueChange", function ChamberPanelComponent_Conditional_3_For_2_Template_p_accordion_valueChange_2_listener($event) { const group_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](group_r4.isActive ? ctx_r1.onAccordionValueChange($event) : ctx_r1.expandOnSwitch(group_r4, $event)); })("click", function ChamberPanelComponent_Conditional_3_For_2_Template_p_accordion_click_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeaterCreate"](3, ChamberPanelComponent_Conditional_3_For_2_For_4_Template, 1, 12, "lib-chamber-card", 7, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"]()(); } if (rf & 2) { const group_r4 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn(ctx_r1.showPhaseLabels() && "overflow-hidden rounded-md bg-(--p-app-surface-card)")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](ctx_r1.showPhaseLabels() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("block", !group_r4.isActive && "opacity-50")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵproperty"]("multiple", true)("cdkDropListDisabled", !group_r4.isActive)("value", group_r4.isActive ? ctx_r1.expandedDrawerPanelIds() : _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵpureFunction0"](8, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeater"](group_r4.cards); } } function ChamberPanelComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementStart"](0, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵlistener"]("click", function ChamberPanelComponent_Conditional_3_Template_div_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.panel.deselectChambers()); }); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeaterCreate"](1, ChamberPanelComponent_Conditional_3_For_2_Template, 5, 9, "div", 3, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵclassMap"](ctx_r1.cn("min-h-full", ctx_r1.showPhaseLabels() && "flex flex-col gap-2.5 px-[9px] py-2")); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵrepeater"](ctx_r1.displayGroups()); } } class ChamberPanelComponent { chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.ChamberFacade); workSessionService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_work_session_work_session_service__WEBPACK_IMPORTED_MODULE_13__.WorkSessionService); panel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_chamber_panel_service__WEBPACK_IMPORTED_MODULE_14__.ChamberPanelService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateService); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.cn; expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); chambers = this.panel.chambers; pendingExpandId; focusedPhaseId; langChange = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toSignal)(this.translate.onLangChange); groups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this.langChange(); const chamberGroups = this.workSessionService.chamberGroups(); const gated = chamberGroups.some(group => group.identification !== undefined); const word = this.translate.instant(gated ? 'multiphase.phase' : 'multiphase.volume'); const triggerUnit = this.translate.instant('multiphase.triggerUnit'); return chamberGroups.map(group => { const detail = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.formatPhaseIdentification)(group.identification, { triggerUnit }); const base = `${word} ${group.label}`; return { ...group, headerLabel: detail ? `${base}: ${detail}` : base }; }); }, ...(ngDevMode ? [{ debugName: "groups" }] : [])); nonEmptyGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.groups().filter(group => group.chambers.length > 0), ...(ngDevMode ? [{ debugName: "nonEmptyGroups" }] : [])); displayGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().map(group => { const cards = group.isActive ? this.chambers() : group.chambers.map(chamber => ({ chamber: { ...chamber }, contentMenuItems: [], moreActions: [], selected: false })); return { ...group, cards }; }), ...(ngDevMode ? [{ debugName: "displayGroups" }] : [])); hasAnyChambers = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().length > 0, ...(ngDevMode ? [{ debugName: "hasAnyChambers" }] : [])); // A single-phase (or single-volume) series has nothing to disambiguate - the phase // header only earns its place once there's more than one group to tell apart. showPhaseLabels = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.nonEmptyGroups().length > 1, ...(ngDevMode ? [{ debugName: "showPhaseLabels" }] : [])); onAccordionValueChange(value) { this.panel.expandedDrawerPanelIds.set(Array.isArray(value) ? value : []); } expandOnSwitch(group, value) { const id = (Array.isArray(value) ? value : []).at(-1); if (id === undefined) return; this.pendingExpandId = id; this.workSessionService.requestActiveChamberVolume(group.phaseId, id); } revealInPhase(phaseId, chamberId) { if (chamberId) { this.workSessionService.requestActiveChamberVolume(phaseId, chamberId); } } handleAnnotationDrop(event) { const currentChambers = [...this.chamberFacade.chambers()]; (0,_angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.moveItemInArray)(currentChambers, event.previousIndex, event.currentIndex); this.chamberFacade.loadChambers(currentChambers); } static ɵfac = function ChamberPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineComponent"]({ type: ChamberPanelComponent, selectors: [["lib-chamber-panel"]], hostAttrs: [1, "block", "h-full", "overflow-y-auto"], decls: 4, vars: 1, consts: [["moreActionsMenu", ""], ["icon", ""], ["severity", "secondary", "variant", "simple", 1, "p-4", 3, "pt"], [3, "class"], ["icon", "info-circle"], [3, "click"], ["cdkDropList", "", 3, "cdkDropListDropped", "valueChange", "click", "multiple", "cdkDropListDisabled", "value"], ["cdkDrag", "true", "cdkDragPreviewContainer", "parent", 1, "block", 3, "cdkDragDisabled", "readOnly", "chamber", "actions", "selected", "menuTrigger", "pt"], [1, "min-w-0", "truncate"], [3, "value", "pt"], ["cdkDrag", "true", "cdkDragPreviewContainer", "parent", 1, "block", 3, "clicked", "updateName", "goTo", "cdkDragDisabled", "readOnly", "chamber", "actions", "selected", "menuTrigger", "pt"]], template: function ChamberPanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵelement"](0, "lib-chamber-menu", null, 0); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditionalCreate"](2, ChamberPanelComponent_Conditional_2_Template, 6, 5, "p-message", 2)(3, ChamberPanelComponent_Conditional_3_Template, 3, 2, "div", 3); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵconditional"](!ctx.hasAnyChambers() ? 2 : 3); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_5__.Accordion, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDropList, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDrag, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.IconComponent, primeng_message__WEBPACK_IMPORTED_MODULE_6__.Message, primeng_tag__WEBPACK_IMPORTED_MODULE_7__.Tag, _chamber_chamber_card_chamber_card_component__WEBPACK_IMPORTED_MODULE_11__.ChamberCardComponent, _chamber_chamber_menu_components_chamber_menu_component__WEBPACK_IMPORTED_MODULE_12__.ChamberMenuComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 77391 /*!******************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/index.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationPanelComponent: () => (/* reexport safe */ _annotation_panel_annotation_panel_component__WEBPACK_IMPORTED_MODULE_0__.AnnotationPanelComponent), /* harmony export */ ChamberPanelComponent: () => (/* reexport safe */ _chamber_panel_chamber_panel_component__WEBPACK_IMPORTED_MODULE_4__.ChamberPanelComponent), /* harmony export */ PlanarReformationPanelComponent: () => (/* reexport safe */ _planar_reformation_panel_planar_reformation_panel_component__WEBPACK_IMPORTED_MODULE_1__.PlanarReformationPanelComponent), /* harmony export */ ProtocolPanelComponent: () => (/* reexport safe */ _protocol_panel_protocol_panel_component__WEBPACK_IMPORTED_MODULE_2__.ProtocolPanelComponent), /* harmony export */ SCurvePanelComponent: () => (/* reexport safe */ _s_curve_panel_s_curve_panel_component__WEBPACK_IMPORTED_MODULE_3__.SCurvePanelComponent) /* harmony export */ }); /* harmony import */ var _annotation_panel_annotation_panel_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-panel/annotation-panel.component */ 3879); /* harmony import */ var _planar_reformation_panel_planar_reformation_panel_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./planar-reformation-panel/planar-reformation-panel.component */ 50075); /* harmony import */ var _protocol_panel_protocol_panel_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./protocol-panel/protocol-panel.component */ 94401); /* harmony import */ var _s_curve_panel_s_curve_panel_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./s-curve-panel/s-curve-panel.component */ 30038); /* harmony import */ var _chamber_panel_chamber_panel_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./chamber-panel/chamber-panel.component */ 40737); /***/ }, /***/ 50075 /*!************************************************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/planar-reformation-panel/planar-reformation-panel.component.ts ***! \************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PlanarReformationPanelComponent: () => (/* binding */ PlanarReformationPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_message__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/message */ 60134); /* harmony import */ var primeng_selectbutton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/selectbutton */ 50857); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../annotation-card/annotation-card.component */ 86628); /* harmony import */ var _volume_viewer_cpr_cpr_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../volume-viewer/cpr/cpr.service */ 26144); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @angular/core */ 14975); /** * Planar-reformation drawer: the splines a reformation can be opened on, and the session * options for the one currently open. Entering from here is the alternative to the spline's * context menu, and selecting a different spline switches the workspace to it. */ const _c0 = () => ({}); const _c1 = () => ({ content: "pt-0 pb-1 ml-8" }); const _c2 = () => ({ root: "py-1 font-normal" }); const _c3 = (a0, a1) => ({ content: a0, header: a1 }); const _forTrack0 = ($index, $item) => $item.id; function PlanarReformationPanelComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](1, "translate"); } if (rf & 2) { const option_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](1, 1, option_r2.label)); } } function PlanarReformationPanelComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 5)(1, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("onClick", function PlanarReformationPanelComponent_Conditional_8_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r3); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r3.confirmEdit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "p-button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("onClick", function PlanarReformationPanelComponent_Conditional_8_Template_p_button_onClick_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r3); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r3.cancelEdit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](2, 2, ctx_r3.confirmLabelKey())); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](4, 4, "planarReformation.cancel")); } } function PlanarReformationPanelComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-button", 12); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("onClick", function PlanarReformationPanelComponent_Conditional_9_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r3.editCenterline()); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](1, 2, ctx_r3.editLabelKey()))("disabled", !ctx_r3.workspaceOpen()); } } function PlanarReformationPanelComponent_Conditional_13_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelement"](0, "lib-icon", 13); } } function PlanarReformationPanelComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-message", 8); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtemplate"](1, PlanarReformationPanelComponent_Conditional_13_ng_template_1_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](3, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction0"](4, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](5, 2, "planarReformation.noSplines")); } } function PlanarReformationPanelComponent_Conditional_14_For_2_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "lib-annotation-card", 16); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("clicked", function PlanarReformationPanelComponent_Conditional_14_For_2_Template_lib_annotation_card_clicked_0_listener() { const spline_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r7).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r3.openReformation(spline_r8)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const spline_r8 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("annotation", spline_r8)("selected", spline_r8.id === ctx_r3.activeSplineId())("pt", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction2"](5, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction0"](3, _c1), _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpureFunction0"](4, _c2))); } } function PlanarReformationPanelComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "p-accordion", 14); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("valueChange", function PlanarReformationPanelComponent_Conditional_14_Template_p_accordion_valueChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r6); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r3.onExpandedChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeaterCreate"](1, PlanarReformationPanelComponent_Conditional_14_For_2_Template, 1, 8, "lib-annotation-card", 15, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("multiple", true)("value", ctx_r3.expandedIds()); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵrepeater"](ctx_r3.splines()); } } const ORIENTATION_OPTIONS = [{ label: 'planarReformation.vertical', value: 'vertical' }, { label: 'planarReformation.horizontal', value: 'horizontal' }]; class PlanarReformationPanelComponent { orientationOptions = ORIENTATION_OPTIONS; session = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.cprSessionStore); // Held here, not inline in the template: a fresh array every change detection // pass would reset the accordion's expanded cards. expandedIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "expandedIds" }] : [])); onExpandedChange(value) { if (Array.isArray(value)) { this.expandedIds.set(value.map(String)); } else if (value === undefined || value === null) { this.expandedIds.set([]); } else { this.expandedIds.set([String(value)]); } } annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.AnnotationFacade); cprService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_volume_viewer_cpr_cpr_service__WEBPACK_IMPORTED_MODULE_13__.CprService); /** Every spline is eligible — the same predicate that gates the annotation-menu entry. */ splines = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.annotationFacade.annotationsWithMeasurements().filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline)(annotation)), ...(ngDevMode ? [{ debugName: "splines" }] : [])); activeSplineId = this.cprService.activeSplineId; workspaceOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.cprService.desiredLayout() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.LayoutType.CPR, ...(ngDevMode ? [{ debugName: "workspaceOpen" }] : [])); editing = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.session.editState() === 'editing', ...(ngDevMode ? [{ debugName: "editing" }] : [])); editLabelKey = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.cprService.activeSplineIsClosed() ? 'planarReformation.editControlPoints' : 'planarReformation.editCenterline', ...(ngDevMode ? [{ debugName: "editLabelKey" }] : [])); confirmLabelKey = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.cprService.activeSplineIsClosed() ? 'planarReformation.confirmControlPoints' : 'planarReformation.confirmCenterline', ...(ngDevMode ? [{ debugName: "confirmLabelKey" }] : [])); /** Opens the workspace, or switches it to another spline when one is already open. */ openReformation(spline) { this.cprService.start(spline); } editCenterline() { this.cprService.beginEdit(); } confirmEdit() { this.cprService.confirmEdit(); } cancelEdit() { this.cprService.cancelEdit(); } exitReformation() { this.cprService.cancel(); } setOrientation(orientation) { this.session.setOrientation(orientation); } static ɵfac = function PlanarReformationPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PlanarReformationPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵdefineComponent"]({ type: PlanarReformationPanelComponent, selectors: [["lib-planar-reformation-panel"]], decls: 15, vars: 12, consts: [["item", ""], ["icon", ""], [1, "space-y-3", "border-b", "border-(--p-app-border-subtle)", "p-4"], [1, "text-muted-color", "mb-2", "text-xs", "tracking-wide", "uppercase"], ["data-test-id", "planar-reformation-panel-p-selectbutton-orientation", "optionLabel", "label", "optionValue", "value", "size", "small", "fluid", "", 3, "ngModelChange", "options", "ngModel", "allowEmpty"], [1, "flex", "w-full", "gap-1"], ["data-test-id", "planar-reformation-panel-p-button-edit-centerline", "icon", "pi pi-pencil", "size", "small", "styleClass", "w-full", 1, "block", "w-full", 3, "label", "disabled"], ["type", "button", "data-test-id", "planar-reformation-panel-button-exit", 1, "hover:bg-surface-600", "w-full", "rounded", "border", "border-(--p-app-border-subtle)", "px-2", "py-1", "text-xs", "disabled:cursor-not-allowed", "disabled:opacity-40", "disabled:hover:bg-transparent", 3, "click", "disabled"], ["severity", "secondary", "variant", "simple", 1, "p-4", 3, "pt"], [3, "multiple", "value"], ["data-test-id", "planar-reformation-panel-p-button-confirm-edit", "icon", "pi pi-check", "size", "small", "styleClass", "w-full", 1, "min-w-0", "flex-1", 3, "onClick", "label"], ["data-test-id", "planar-reformation-panel-p-button-cancel-edit", "icon", "pi pi-times", "size", "small", "severity", "secondary", "outlined", "", 3, "onClick", "label"], ["data-test-id", "planar-reformation-panel-p-button-edit-centerline", "icon", "pi pi-pencil", "size", "small", "styleClass", "w-full", 1, "block", "w-full", 3, "onClick", "label", "disabled"], ["icon", "info-circle"], [3, "valueChange", "multiple", "value"], ["readOnly", "", 1, "block", 3, "annotation", "selected", "pt"], ["readOnly", "", 1, "block", 3, "clicked", "annotation", "selected", "pt"]], template: function PlanarReformationPanelComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](0, "div", 2)(1, "fieldset")(2, "legend", 3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](5, "p-selectbutton", 4); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("ngModelChange", function PlanarReformationPanelComponent_Template_p_selectbutton_ngModelChange_5_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx.setOrientation($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtemplate"](6, PlanarReformationPanelComponent_ng_template_6_Template, 2, 3, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](8, PlanarReformationPanelComponent_Conditional_8_Template, 5, 6, "div", 5)(9, PlanarReformationPanelComponent_Conditional_9_Template, 2, 4, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementStart"](10, "button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵlistener"]("click", function PlanarReformationPanelComponent_Template_button_click_10_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx.exitReformation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipe"](12, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditionalCreate"](13, PlanarReformationPanelComponent_Conditional_13_Template, 6, 5, "p-message", 8)(14, PlanarReformationPanelComponent_Conditional_14_Template, 3, 2, "p-accordion", 9); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](4, 8, "planarReformation.orientation"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("options", ctx.orientationOptions)("ngModel", ctx.session.orientation())("allowEmpty", false); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx.editing() ? 8 : 9); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵproperty"]("disabled", !ctx.workspaceOpen()); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵpipeBind1"](12, 10, "planarReformation.exit"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_14__["ɵɵconditional"](ctx.splines().length === 0 ? 13 : 14); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_4__.Accordion, _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_12__.AnnotationCardComponent, primeng_button__WEBPACK_IMPORTED_MODULE_5__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_5__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgModel, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.IconComponent, primeng_message__WEBPACK_IMPORTED_MODULE_6__.Message, primeng_selectbutton__WEBPACK_IMPORTED_MODULE_7__.SelectButtonModule, primeng_selectbutton__WEBPACK_IMPORTED_MODULE_7__.SelectButton, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 94401 /*!****************************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/protocol-panel/protocol-panel.component.ts ***! \****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolPanelComponent: () => (/* binding */ ProtocolPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 13329); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../annotation-card/annotation-card.component */ 86628); /* harmony import */ var _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _dicom_importer_components_review_dialog_review_dialog_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../../dicom-importer/components/review-dialog/review-dialog.component */ 80325); /* harmony import */ var _dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../dicom-importer/services/annotation-export-bridge.service */ 68674); /* harmony import */ var _protocols__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../../protocols */ 61632); /* harmony import */ var _protocols_protocol_form_card_protocol_form_card_component__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../../protocols/protocol-form-card/protocol-form-card.component */ 47716); /* harmony import */ var _services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../services/annotation-panel.service */ 56105); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["placeholder"]; const _c1 = () => ({ root: "py-1 font-normal" }); const _c2 = a0 => ({ header: a0 }); const _c3 = () => ({ content: "pt-0 pb-1 ml-8" }); const _c4 = (a0, a1) => ({ content: a0, header: a1 }); const _forTrack0 = ($index, $item) => $item.placeholder.id; function ProtocolPanelComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](0, "div", 4)(1, "p-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("click", function ProtocolPanelComponent_Conditional_4_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.onStartClicked()); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](4, "p-button", 9); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("click", function ProtocolPanelComponent_Conditional_4_Template_p_button_click_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.onClearClicked()); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("disabled", ctx_r2.startDisabled()); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipeBind1"](3, 4, ctx_r2.isEmpty() ? "protocols.start" : "protocols.resume"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("disabled", ctx_r2.clearDisabled()); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipeBind1"](6, 6, "protocols.clear"), " "); } } function ProtocolPanelComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](0, "div", 4)(1, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("click", function ProtocolPanelComponent_Conditional_5_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.openReview()); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("disabled", !ctx_r2.canReview())("pTooltip", ctx_r2.canReview() ? "" : _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipeBind1"](2, 3, "protocols.review.disabledHint")); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpipeBind1"](4, 5, "protocols.review.cta"), " "); } } function ProtocolPanelComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](0, "lib-protocol-form-card", 11); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("click", function ProtocolPanelComponent_Conditional_9_Template_lib_protocol_form_card_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.openForm()); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("formDefinition", ctx)("blocked", ctx_r2.formValid() === true && !ctx_r2.canProceed())("complete", ctx_r2.formValid() === true)("invalid", ctx_r2.formValid() === false)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction1"](6, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction0"](5, _c1))); } } function ProtocolPanelComponent_For_11_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](0, "lib-annotation-card", 14); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("show", function ProtocolPanelComponent_For_11_Conditional_0_Template_lib_annotation_card_show_0_listener() { const annotation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.onShowAnnotation(annotation_r7.id)); })("hide", function ProtocolPanelComponent_For_11_Conditional_0_Template_lib_annotation_card_hide_0_listener() { const annotation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.onHideAnnotation(annotation_r7.id)); })("goTo", function ProtocolPanelComponent_For_11_Conditional_0_Template_lib_annotation_card_goTo_0_listener() { const annotation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.onGoToAnnotation(annotation_r7.id)); })("updateName", function ProtocolPanelComponent_For_11_Conditional_0_Template_lib_annotation_card_updateName_0_listener($event) { const annotation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.onUpdateAnnotationName($event, annotation_r7.id)); })("clicked", function ProtocolPanelComponent_For_11_Conditional_0_Template_lib_annotation_card_clicked_0_listener($event) { const annotation_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.handleAnnotationCardClick($event, annotation_r7.id)); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"](); } if (rf & 2) { const item_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); const annotationActionsMenu_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("annotation", ctx)("actions", item_r8.moreActions)("selected", item_r8.annotationSelected)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction2"](7, _c4, _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction0"](5, _c3), _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction0"](6, _c1)))("menuTrigger", annotationActionsMenu_r9); } } function ProtocolPanelComponent_For_11_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r10 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](0, "lib-placeholder-card", 15, 1); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("click", function ProtocolPanelComponent_For_11_Conditional_1_Template_lib_placeholder_card_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r10); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.panel.deselectAnnotations()); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"](); } if (rf & 2) { const item_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"]().$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("placeholder", item_r8.placeholder)("active", ctx_r2.canProceed() && ctx_r2.isPlaceholderActive(item_r8.placeholder))("disabled", !ctx_r2.canProceed())("pt", _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction1"](5, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵpureFunction0"](4, _c1))); } } function ProtocolPanelComponent_For_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditionalCreate"](0, ProtocolPanelComponent_For_11_Conditional_0_Template, 1, 10, "lib-annotation-card", 12)(1, ProtocolPanelComponent_For_11_Conditional_1_Template, 2, 7, "lib-placeholder-card", 13); } if (rf & 2) { let tmp_11_0; const item_r8 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditional"]((tmp_11_0 = item_r8.annotation) ? 0 : 1, tmp_11_0); } } class ProtocolPanelComponent { confirmationService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_7__.ConfirmationService); panel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_20__.AnnotationPanelService); protocolCreation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_protocols__WEBPACK_IMPORTED_MODULE_18__.ProtocolCreationService); protocolFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_13__.ProtocolFacade); placeholderCards = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChildren)('placeholder', ...(ngDevMode ? [{ debugName: "placeholderCards" }] : [])); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslateService); exportBridge = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_dicom_importer_services_annotation_export_bridge_service__WEBPACK_IMPORTED_MODULE_17__.AnnotationExportBridge); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_9__.DialogService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_7__.MessageService); reviewContext = this.exportBridge.reviewContext; canReview = this.exportBridge.canReview; // Don't use `panel.expandedPanelIds` because we want to keep new annotations minimized. expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); protocols = this.protocolFacade.protocolDefinitions; activeProtocol = this.protocolFacade.activeProtocol; isEmpty = this.protocolCreation.isEmpty; isStarted = this.protocolCreation.isBeingCreated; _focusOnPlaceholder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const active = this.protocolCreation.activePlaceholder(); const cards = this.placeholderCards(); if (active) { const card = cards.find(card => card.placeholder() === active); card?.scrollTo(); } }, ...(ngDevMode ? [{ debugName: "_focusOnPlaceholder" }] : [])); startDisabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const isStarted = this.isStarted(); const { definition, instance } = this.activeProtocol(); // Can't start if already in-progress / finished, or if there's no active protocol return isStarted || !definition || (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.isProtocolComplete)(definition, instance); }, ...(ngDevMode ? [{ debugName: "startDisabled" }] : [])); clearDisabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const isStarted = this.isStarted(); const { definition, instance } = this.activeProtocol(); const noFormValues = Object.keys(instance?.formValues ?? {}).length === 0; // Can't clear if creation in-progress, empty, or if there's no active protocol return isStarted || !definition || (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.isProtocolEmpty)(instance) && noFormValues; }, ...(ngDevMode ? [{ debugName: "clearDisabled" }] : [])); protocolItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const annotations = this.panel.annotations(); const { definition, instance } = this.activeProtocol(); if (!definition) { return []; } return definition.placeholders.map(placeholder => { const annotation = annotations.find(({ annotation: { id } }) => id === instance?.placeholderMappings[placeholder.id]); return { annotation: annotation?.annotation, annotationSelected: annotation?.selected ?? false, menuItems: annotation?.contentMenuItems ?? [], moreActions: annotation?.moreActions ?? [], placeholder }; }); }, ...(ngDevMode ? [{ debugName: "protocolItems" }] : [])); onProtocolSelect(event) { this.protocolFacade.setActiveProtocol(event.value); } onStartClicked() { this.protocolCreation.start(); } onClearClicked() { const { instance } = this.activeProtocol(); if (instance !== undefined) { this.confirmationService.confirm({ accept: () => { this.protocolCreation.clear(); }, acceptButtonProps: { label: this.translate.instant('protocols.confirmClear.cta.accept'), severity: 'danger' }, acceptLabel: this.translate.instant('protocols.confirmClear.cta.accept'), header: this.translate.instant('protocols.confirmClear.title'), message: this.translate.instant('protocols.confirmClear.message'), rejectButtonProps: { label: this.translate.instant('common.cancel'), outlined: true, severity: 'secondary' } }); } } isPlaceholderActive(placeholder) { return this.protocolCreation.activePlaceholder()?.id === placeholder.id; } onAccordionValueChange(value) { this.expandedDrawerPanelIds.set(Array.isArray(value) ? value : []); } formDefinition = this.protocolCreation.activeProtocolForm; formValid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { instance } = this.activeProtocol(); const formDefinition = this.formDefinition(); if (formDefinition === undefined) { return; } if (instance?.formValues === undefined) { return; } return (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.isProtocolFormValid)(formDefinition, instance.formValues); }, ...(ngDevMode ? [{ debugName: "formValid" }] : [])); canProceed = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const { instance } = this.activeProtocol(); const formDefinition = this.formDefinition(); // No form to check if (formDefinition === undefined) { return true; } return (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_12__.canProceedFromProtocolForm)(formDefinition, instance?.formValues); }, ...(ngDevMode ? [{ debugName: "canProceed" }] : [])); openForm() { this.protocolCreation.openProtocolForm(); } openReview() { const reference = this.dialogService.open(_dicom_importer_components_review_dialog_review_dialog_component__WEBPACK_IMPORTED_MODULE_16__.ReviewDialogComponent, { closable: true, header: this.translate.instant('dicomImporter.reviewDialog.title'), width: '28rem' }); reference?.onClose.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_4__.take)(1)).subscribe(outcome => { if (!outcome) return; this.messageService.add({ ...(outcome.detail ? { detail: outcome.detail } : {}), severity: outcome.severity, summary: this.translate.instant(outcome.messageKey) }); }); } static ɵfac = function ProtocolPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵdefineComponent"]({ type: ProtocolPanelComponent, selectors: [["lib-protocol-panel"]], viewQuery: function ProtocolPanelComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵviewQuerySignal"](ctx.placeholderCards, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵqueryAdvance"](); } }, decls: 12, vars: 7, consts: [["annotationActionsMenu", ""], ["placeholder", ""], [1, "flex", "h-full", "flex-col"], ["data-test-id", "protocol-panel-p-select-active-protocol", "optionLabel", "name", "optionValue", "id", 1, "m-2", "mb-0", 3, "onChange", "ngModel", "options"], [1, "border-surface-800", "flex", "h-16", "w-full", "items-center", "justify-center", "gap-4", "border-b"], [1, "flex", "h-full", "flex-col", "overflow-x-clip", "overflow-y-auto"], [3, "valueChange", "multiple", "value"], [3, "formDefinition", "blocked", "complete", "invalid", "pt"], ["data-test-id", "protocol-panel-p-button-start", 3, "click", "disabled"], ["data-test-id", "protocol-panel-p-button-clear", 3, "click", "disabled"], ["data-test-id", "protocol-panel-p-button-review", 3, "click", "disabled", "pTooltip"], [3, "click", "formDefinition", "blocked", "complete", "invalid", "pt"], [1, "block", 3, "annotation", "actions", "selected", "pt", "menuTrigger"], [3, "placeholder", "active", "disabled", "pt"], [1, "block", 3, "show", "hide", "goTo", "updateName", "clicked", "annotation", "actions", "selected", "pt", "menuTrigger"], [3, "click", "placeholder", "active", "disabled", "pt"]], template: function ProtocolPanelComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelement"](0, "lib-annotation-menu", null, 0); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](2, "div", 2)(3, "p-select", 3); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("onChange", function ProtocolPanelComponent_Template_p_select_onChange_3_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onProtocolSelect($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditionalCreate"](4, ProtocolPanelComponent_Conditional_4_Template, 7, 8, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditionalCreate"](5, ProtocolPanelComponent_Conditional_5_Template, 5, 7, "div", 4); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](6, "div", 5)(7, "p-accordion", 6); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵlistener"]("valueChange", function ProtocolPanelComponent_Template_p_accordion_valueChange_7_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onAccordionValueChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementStart"](8, "ul"); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditionalCreate"](9, ProtocolPanelComponent_Conditional_9_Template, 1, 8, "lib-protocol-form-card", 7); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrepeaterCreate"](10, ProtocolPanelComponent_For_11_Template, 2, 1, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵelementEnd"]()()()(); } if (rf & 2) { let tmp_1_0; let tmp_3_0; let tmp_7_0; _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("ngModel", (tmp_1_0 = ctx.activeProtocol().definition) == null ? null : tmp_1_0.id)("options", ctx.protocols()); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditional"]((tmp_3_0 = ctx.activeProtocol().definition) ? 4 : -1, tmp_3_0); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditional"](ctx.reviewContext() ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵproperty"]("multiple", true)("value", ctx.expandedDrawerPanelIds()); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵconditional"]((tmp_7_0 = ctx.formDefinition()) ? 9 : -1, tmp_7_0); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrepeater"](ctx.protocolItems()); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_6__.Accordion, _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_14__.AnnotationCardComponent, _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_15__.AnnotationMenuComponent, primeng_button__WEBPACK_IMPORTED_MODULE_8__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_8__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgModel, _protocols__WEBPACK_IMPORTED_MODULE_18__.PlaceholderCardComponent, _protocols_protocol_form_card_protocol_form_card_component__WEBPACK_IMPORTED_MODULE_19__.ProtocolFormCardComponent, primeng_select__WEBPACK_IMPORTED_MODULE_10__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_10__.Select, primeng_tooltip__WEBPACK_IMPORTED_MODULE_11__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_11__.Tooltip, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 30038 /*!**************************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/s-curve-panel/s-curve-panel.component.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurvePanelComponent: () => (/* binding */ SCurvePanelComponent) /* harmony export */ }); /* harmony import */ var _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/drag-drop */ 94355); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_message__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/message */ 60134); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../annotation-menu/annotation-menu-item.service */ 39860); /* harmony import */ var _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _s_curve_card_s_curve_card_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../s-curve-card/s-curve-card.component */ 31982); /* harmony import */ var _s_curve_graph_s_curve_graph_component__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../s-curve-graph/s-curve-graph.component */ 1336); /* harmony import */ var _s_curve_relative_measurement_card_s_curve_relative_measurement_card_component__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../s-curve-relative-measurement-card/s-curve-relative-measurement-card.component */ 8452); /* harmony import */ var _s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../s-curve-relative-measurements/s-curve-relative-measurements.service */ 17464); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({}); const _c1 = () => ({ content: "pt-0 pb-1 ml-8" }); const _c2 = () => ({ root: "py-1 font-normal" }); const _c3 = (a0, a1) => ({ content: a0, header: a1 }); const _forTrack0 = ($index, $item) => $item.id; function SCurvePanelComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "lib-s-curve-graph", 5); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("toggleMaximize", function SCurvePanelComponent_Conditional_3_Template_lib_s_curve_graph_toggleMaximize_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.toggleMaximizeSCurveGraph.emit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("showMaximizeButton", true)("isMaximized", ctx_r1.isMaximized()); } } function SCurvePanelComponent_Conditional_4_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelement"](0, "lib-icon", 6); } } function SCurvePanelComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "p-message", 4); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtemplate"](1, SCurvePanelComponent_Conditional_4_ng_template_1_Template, 1, 0, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](3, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](4, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpipeBind1"](5, 2, "volumeViewer.drawer.content.noSCurvesFound")); } } function SCurvePanelComponent_Conditional_5_For_3_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "lib-s-curve-card", 12); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("show", function SCurvePanelComponent_Conditional_5_For_3_Template_lib_s_curve_card_show_0_listener() { const sCurve_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSetSCurveVisibility(sCurve_r5, true)); })("hide", function SCurvePanelComponent_Conditional_5_For_3_Template_lib_s_curve_card_hide_0_listener() { const sCurve_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSetSCurveVisibility(sCurve_r5, false)); })("goTo", function SCurvePanelComponent_Conditional_5_For_3_Template_lib_s_curve_card_goTo_0_listener() { const sCurve_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleGoToSCurve(sCurve_r5)); })("clicked", function SCurvePanelComponent_Conditional_5_For_3_Template_lib_s_curve_card_clicked_0_listener($event) { const sCurve_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSCurveCardClick($event, sCurve_r5)); })("updateName", function SCurvePanelComponent_Conditional_5_For_3_Template_lib_s_curve_card_updateName_0_listener($event) { const sCurve_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleUpdateSCurveName(sCurve_r5, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const sCurve_r5 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); const moreActionsMenu_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("menuTrigger", moreActionsMenu_r6)("actions", sCurve_r5.menuItems)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction2"](7, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](5, _c1), _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](6, _c2)))("sCurve", sCurve_r5)("selected", sCurve_r5.selected); } } function SCurvePanelComponent_Conditional_5_For_6_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "lib-s-curve-relative-measurement-card", 13); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("show", function SCurvePanelComponent_Conditional_5_For_6_Template_lib_s_curve_relative_measurement_card_show_0_listener() { const measurement_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSetMeasurementVisibility(measurement_r8, true)); })("hide", function SCurvePanelComponent_Conditional_5_For_6_Template_lib_s_curve_relative_measurement_card_hide_0_listener() { const measurement_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSetMeasurementVisibility(measurement_r8, false)); })("goTo", function SCurvePanelComponent_Conditional_5_For_6_Template_lib_s_curve_relative_measurement_card_goTo_0_listener() { const measurement_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleGoToMeasurement(measurement_r8)); })("clicked", function SCurvePanelComponent_Conditional_5_For_6_Template_lib_s_curve_relative_measurement_card_clicked_0_listener($event) { const measurement_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleMeasurementCardClick($event, measurement_r8)); })("updateName", function SCurvePanelComponent_Conditional_5_For_6_Template_lib_s_curve_relative_measurement_card_updateName_0_listener($event) { const measurement_r8 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r7).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleUpdateMeasurementName(measurement_r8, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const measurement_r8 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](2); const moreActionsMenu_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵreference"](1); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("menuTrigger", moreActionsMenu_r6)("actions", measurement_r8.menuItems)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction2"](7, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](5, _c1), _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵpureFunction0"](6, _c2)))("measurement", measurement_r8)("selected", measurement_r8.selected); } } function SCurvePanelComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](0, "p-accordion", 7); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("click", function SCurvePanelComponent_Conditional_5_Template_p_accordion_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](1, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("cdkDropListDropped", function SCurvePanelComponent_Conditional_5_Template_div_cdkDropListDropped_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleSCurveDrop($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵrepeaterCreate"](2, SCurvePanelComponent_Conditional_5_For_3_Template, 1, 10, "lib-s-curve-card", 9, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](4, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("cdkDropListDropped", function SCurvePanelComponent_Conditional_5_Template_div_cdkDropListDropped_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleMeasurementDrop($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵrepeaterCreate"](5, SCurvePanelComponent_Conditional_5_For_6_Template, 1, 10, "lib-s-curve-relative-measurement-card", 10, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](7, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵlistener"]("click", function SCurvePanelComponent_Conditional_5_Template_div_click_7_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.handleBackgroundClick()); }); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵproperty"]("multiple", true)("value", ctx_r1.expandedDrawerPanelIds()); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵrepeater"](ctx_r1.sCurves()); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵrepeater"](ctx_r1.relativeMeasurements()); } } class SCurvePanelComponent { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.AnnotationFacade); annotationMenuItemService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_10__.AnnotationMenuItemService); sCurveFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.SCurveFacade); sCurveRelativeMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_15__.SCurveRelativeMeasurementsService); uiFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.UiFacade); expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); // Whether the s-curve view is currently the fullscreen maximized panel - passed down from // whichever ancestor owns the viewport layout state, so the button's icon reflects it. isMaximized = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "isMaximized" }] : [])); // The drawer has no other way to reach the fullscreen s-curve view - forwarded up to // whichever ancestor owns the viewport layout state. toggleMaximizeSCurveGraph = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); // Maximized and detached are independent states (TVC-1238) - hide the sidebar copy while // either is true, but neither toggle should ever flip the other. Without the isMaximized // check, maximizing (which the page enters without first detaching, as a shortcut - see // toggleSCurveMaximizeFromSidebar) would show the sidebar copy at the same time as the // fullscreen view. showGraph = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => !this.uiFacade.sCurveGraphDetached() && !this.isMaximized(), ...(ngDevMode ? [{ debugName: "showGraph" }] : [])); sCurves = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const selectedIds = this.sCurveFacade.selectedIds(); const sCurves = this.sCurveFacade.sCurves(); return sCurves.map(sCurve => ({ ...sCurve, menuItems: this.annotationMenuItemService.menuItemsForSCurve(sCurve), selected: selectedIds.includes(sCurve.id) })); }, ...(ngDevMode ? [{ debugName: "sCurves" }] : [])); relativeMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const selectedIds = this.sCurveFacade.selectedIds(); const measurements = this.sCurveFacade.relativeMeasurements(); return measurements.map(measurement => ({ ...measurement, menuItems: this.annotationMenuItemService.menuItemsForSCurveRelativeMeasurement(measurement), selected: selectedIds.includes(measurement.id) })); }, ...(ngDevMode ? [{ debugName: "relativeMeasurements" }] : [])); handleSCurveDrop(event) { const sCurves = [...this.sCurveFacade.sCurves()]; (0,_angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.moveItemInArray)(sCurves, event.previousIndex, event.currentIndex); this.sCurveFacade.loadSCurves(sCurves); } handleMeasurementDrop(event) { const measurements = [...this.sCurveFacade.relativeMeasurements()]; (0,_angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.moveItemInArray)(measurements, event.previousIndex, event.currentIndex); this.sCurveFacade.reorderRelativeMeasurements(measurements); } handleSCurveCardClick(event, sCurve) { if (event.ctrlKey) { this.sCurveFacade.toggleSelectSCurve(sCurve.id); } else if (event.shiftKey) { this.sCurveFacade.selectSCurvesRange(sCurve.id); } else { this.sCurveFacade.selectSCurves([sCurve.id]); } } handleSetSCurveVisibility(sCurve, visible) { this.sCurveFacade.setSCurveVisibility([sCurve.id], visible); } handleGoToSCurve(sCurve) { // Control-point curves have no backing annotation to center the camera on. if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_7__.sCurveIsSpline)(sCurve)) { this.annotationFacade.goToAnnotation(sCurve.id, true); } } handleUpdateSCurveName(sCurve, name) { this.sCurveFacade.updateSCurve({ id: sCurve.id, name }); } handleMeasurementCardClick(event, measurement) { if (event.ctrlKey) { this.sCurveFacade.toggleSelectSCurve(measurement.id); } else if (event.shiftKey) { this.sCurveFacade.selectSCurvesRange(measurement.id); } else { this.sCurveFacade.selectSCurves([measurement.id]); } } handleSetMeasurementVisibility(measurement, visible) { this.sCurveFacade.setSCurveVisibility([measurement.id], visible); } handleGoToMeasurement(measurement) { this.sCurveRelativeMeasurements.goTo(measurement); } handleUpdateMeasurementName(measurement, name) { this.sCurveFacade.updateRelativeMeasurement({ id: measurement.id, name }); } handleBackgroundClick() { this.sCurveFacade.selectSCurves([]); } static ɵfac = function SCurvePanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurvePanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵdefineComponent"]({ type: SCurvePanelComponent, selectors: [["lib-s-curve-panel"]], inputs: { isMaximized: [1, "isMaximized"] }, outputs: { toggleMaximizeSCurveGraph: "toggleMaximizeSCurveGraph" }, decls: 6, vars: 2, consts: [["moreActionsMenu", ""], ["icon", ""], [1, "flex", "h-full", "flex-col"], [3, "showMaximizeButton", "isMaximized"], ["severity", "secondary", "variant", "simple", 1, "p-4", 3, "pt"], [3, "toggleMaximize", "showMaximizeButton", "isMaximized"], ["icon", "info-circle"], [3, "click", "multiple", "value"], ["cdkDropList", "", 3, "cdkDropListDropped"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "menuTrigger", "actions", "pt", "sCurve", "selected"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "menuTrigger", "actions", "pt", "measurement", "selected"], [1, "flex-1", 3, "click"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "show", "hide", "goTo", "clicked", "updateName", "menuTrigger", "actions", "pt", "sCurve", "selected"], ["cdkDrag", "", "cdkDragPreviewContainer", "parent", 1, "block", 3, "show", "hide", "goTo", "clicked", "updateName", "menuTrigger", "actions", "pt", "measurement", "selected"]], template: function SCurvePanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelement"](0, "lib-annotation-menu", null, 0); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementStart"](2, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditionalCreate"](3, SCurvePanelComponent_Conditional_3_Template, 1, 2, "lib-s-curve-graph", 3); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditionalCreate"](4, SCurvePanelComponent_Conditional_4_Template, 6, 5, "p-message", 4)(5, SCurvePanelComponent_Conditional_5_Template, 8, 2); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditional"](ctx.showGraph() ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_16__["ɵɵconditional"](ctx.sCurves().length === 0 ? 4 : 5); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_5__.Accordion, _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_11__.AnnotationMenuComponent, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDropList, _angular_cdk_drag_drop__WEBPACK_IMPORTED_MODULE_0__.CdkDrag, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_9__.IconComponent, primeng_message__WEBPACK_IMPORTED_MODULE_6__.Message, _s_curve_card_s_curve_card_component__WEBPACK_IMPORTED_MODULE_12__.SCurveCardComponent, _s_curve_graph_s_curve_graph_component__WEBPACK_IMPORTED_MODULE_13__.SCurveGraphComponent, _s_curve_relative_measurement_card_s_curve_relative_measurement_card_component__WEBPACK_IMPORTED_MODULE_14__.SCurveRelativeMeasurementCardComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 56105 /*!**********************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/services/annotation-panel.service.ts ***! \**********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationPanelService: () => (/* binding */ AnnotationPanelService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../annotation-menu/annotation-menu-item.service */ 39860); /** * Common annotation-related functionality that is used from multiple sidebar panels * (eg. Annotation Panel, Protocol Panel) */ class AnnotationPanelService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_2__.AnnotationFacade); annotationMenuItemService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_3__.AnnotationMenuItemService); seenAnnotationIds = new Set(); expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const ids = this.annotations().map(a => a.annotation.id); const newIds = ids.filter(id => !this.seenAnnotationIds.has(id)); if (newIds.length > 0) { for (const id of newIds) this.seenAnnotationIds.add(id); this.expandedDrawerPanelIds.update(current => [...current, ...newIds]); } }); } annotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const selectedIds = this.annotationFacade.selectedIds(); return this.annotationFacade.annotationsWithMeasurements().map(annotation => { const menuItems = this.annotationMenuItemService.menuItemsForAnnotation(annotation); const contentMenuItems = menuItems.filter(({ includeInCard }) => includeInCard); return { annotation, contentMenuItems, moreActions: menuItems, selected: selectedIds.includes(annotation.id) }; }); }, ...(ngDevMode ? [{ debugName: "annotations" }] : [])); handleAnnotationCardClick(event, annotationId) { if (event.ctrlKey) { this.annotationFacade.toggleSelectAnnotation(annotationId); } else if (event.shiftKey) { this.annotationFacade.selectAnnotationRange(annotationId); } else { this.annotationFacade.selectAnnotations([annotationId]); } } onShowAnnotation(annotationId) { this.annotationMenuItemService.showAnnotation(annotationId); } onHideAnnotation(annotationId) { this.annotationMenuItemService.hideAnnotation(annotationId); } onGoToAnnotation(annotationId) { this.annotationMenuItemService.goToAnnotation(annotationId); } onUpdateAnnotationName(newName, annotationId) { this.annotationMenuItemService.updateAnnotationName(annotationId, newName); } onAccordionValueChange(value) { this.expandedDrawerPanelIds.set(Array.isArray(value) ? value : []); } deselectAnnotations() { this.annotationFacade.selectAnnotations([]); } static ɵfac = function AnnotationPanelService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationPanelService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AnnotationPanelService, factory: AnnotationPanelService.ɵfac }); } /***/ }, /***/ 38164 /*!*******************************************************************************!*\ !*** ./libs/feature/src/lib/sidebar-panels/services/chamber-panel.service.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberPanelService: () => (/* binding */ ChamberPanelService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../chamber/chamber-menu/chamber-menu-item.service */ 44189); class ChamberPanelService { chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_2__.ChamberFacade); chamberMenuItemService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_3__.ChamberMenuItemService); seenChambersIds = new Set(); expandedDrawerPanelIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "expandedDrawerPanelIds" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const ids = this.chambers().map(a => a.chamber.id); const newIds = ids.filter(id => !this.seenChambersIds.has(id)); if (newIds.length > 0) { for (const id of newIds) this.seenChambersIds.add(id); this.expandedDrawerPanelIds.update(current => [...current, ...newIds]); } }); } chambers = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const selectedIds = this.chamberFacade.selectedIds(); return this.chamberFacade.chambers().map(chamber => { const menuItems = this.chamberMenuItemService.menuItemsForChamber(chamber); const contentMenuItems = menuItems.filter(({ includeInCard }) => includeInCard); return { chamber, contentMenuItems, moreActions: menuItems, selected: selectedIds.includes(chamber.id) }; }); }, ...(ngDevMode ? [{ debugName: "chambers" }] : [])); deselectChambers() { this.chamberFacade.selectChambers([]); } handleChamberCardClick(event, chamberId) { if (event.ctrlKey) { this.chamberFacade.toggleSelectChamber(chamberId); } else if (event.shiftKey) { this.chamberFacade.selectChamberRange(chamberId); } else { this.chamberFacade.selectChambers([chamberId]); } } onUpdateChamberName(newName, chamberId) { this.chamberMenuItemService.updateChamberName(chamberId, newName); } onGoToChamber(chamber) { this.chamberMenuItemService.goToChamber(chamber); } static ɵfac = function ChamberPanelService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberPanelService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ChamberPanelService, factory: ChamberPanelService.ɵfac }); } /***/ }, /***/ 79428 /*!****************************************************************************!*\ !*** ./libs/feature/src/lib/theme-preview/theme-preview-page.component.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ThemePreviewPageComponent: () => (/* binding */ ThemePreviewPageComponent) /* harmony export */ }); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_checkbox__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/checkbox */ 10026); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_datepicker__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/datepicker */ 83203); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_multiselect__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/multiselect */ 58612); /* harmony import */ var primeng_panel__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/panel */ 22949); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_progressbar__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/progressbar */ 95932); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_skeleton__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/skeleton */ 65528); /* harmony import */ var primeng_slider__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! primeng/slider */ 31486); /* harmony import */ var primeng_splitter__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/splitter */ 592); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tabs__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! primeng/tabs */ 70021); /* harmony import */ var primeng_tag__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/tag */ 37587); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! primeng/api */ 62751); const _c0 = () => ({ height: "8rem" }); const _c1 = () => [60, 40]; const _forTrack0 = ($index, $item) => $item.name; function ThemePreviewPageComponent_For_13_For_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 71); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](1, "div", 72); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](2, "div", 73); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const token_r2 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵstyleProp"]("background", "var(" + token_r2 + ")"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("title", token_r2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", token_r2, " "); } } function ThemePreviewPageComponent_For_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "section")(1, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](3, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeaterCreate"](4, ThemePreviewPageComponent_For_13_For_5_Template, 4, 4, "div", 71, _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const group_r3 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", group_r3.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeater"](group_r3.tokens); } } function ThemePreviewPageComponent_For_19_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 8)(1, "div", 74); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](3, "div", 75); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const token_r4 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("title", token_r4.name); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate1"](" ", token_r4.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](token_r4.value || "\u2014"); } } function ThemePreviewPageComponent_ng_template_74_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "tr")(1, "th", 76); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2, " Name "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](3, "p-sortIcon", 77); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](4, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](5, "Modality"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](6, "th"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](7, "Series"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } } function ThemePreviewPageComponent_ng_template_75_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "tr", 78)(1, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](3, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](4, "p-tag", 79); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](5, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); } if (rf & 2) { const row_r5 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("pSelectableRow", row_r5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](row_r5.name); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("value", row_r5.modality); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtextInterpolate"](row_r5.series); } } function ThemePreviewPageComponent_ng_template_128_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 80); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1, "Left panel"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } } function ThemePreviewPageComponent_ng_template_129_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 80); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](1, "Right panel"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); } } const scale = (prefix, shades) => shades.map(s => `${prefix}-${s}`); const SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]; const flattenVariables = (group, prefix) => Object.entries(group).flatMap(([key, value]) => typeof value === 'object' ? flattenVariables(value, `${prefix}-${key}`) : [`${prefix}-${key}`]); const FIGMA_PRIMITIVE_GROUPS = new Set(['amber', 'blue', 'emerald', 'green', 'neutral', 'red', 'slate']); const figmaVariables = predicate => Object.entries(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.appColorTokens).filter(([group]) => predicate(group)).flatMap(([group, tokens]) => typeof tokens === 'object' ? flattenVariables(tokens, `--p-app-${group}`) : [`--p-app-${group}`]); /** * Dev-only gallery of every semantic and app design token plus one of each * commonly used PrimeNG component. This is the review surface for a future * light color scheme: toggle the `dark` class on and everything on * this page must remain legible. */ class ThemePreviewPageComponent { tokenGroups = [{ name: 'Primary', tokens: scale('--p-primary', SHADES) }, { name: 'Surface', tokens: ['--p-surface-0', ...scale('--p-surface', SHADES)] }, { name: 'Text', tokens: ['--p-text-color', '--p-text-hover-color', '--p-text-muted-color', '--p-text-hover-muted-color'] }, { name: 'Content', tokens: ['--p-content-background', '--p-content-hover-background', '--p-content-border-color'] }, { name: 'Form field', tokens: ['--p-form-field-background', '--p-form-field-border-color', '--p-form-field-color', '--p-form-field-disabled-background', '--p-form-field-placeholder-color'] }, { name: 'Highlight / focus / mask', tokens: ['--p-highlight-background', '--p-highlight-focus-background', '--p-focus-ring-color', '--p-mask-background'] }, { name: 'Overlays', tokens: ['--p-overlay-select-background', '--p-overlay-popover-background', '--p-overlay-modal-background'] }, { name: 'Figma: primitives', tokens: figmaVariables(group => FIGMA_PRIMITIVE_GROUPS.has(group)) }, { name: 'Figma: semantic + app aliases', tokens: figmaVariables(group => !FIGMA_PRIMITIVE_GROUPS.has(group) && group !== 'annotation' && group !== 'palette') }, { name: 'Figma: annotation (protocol-controlled, TVC-1003)', tokens: figmaVariables(group => group === 'annotation') }, { name: 'Figma: annotation picker palettes', tokens: figmaVariables(group => group === 'palette') }]; rootStyles = globalThis.getComputedStyle(globalThis.document.documentElement); figmaScales = flattenVariables(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.appScaleTokens, '--p-app').map(name => ({ name, value: this.rootStyles.getPropertyValue(name) })); text = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl('Filled value'); emptyText = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(''); disabledText = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl({ disabled: true, value: 'Disabled' }); checked = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(true); unchecked = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(false); slider = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(40); date = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(undefined); select = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl(undefined); multi = new _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControl([]); options = [{ label: 'Option A', value: 'a' }, { label: 'Option B', value: 'b' }, { label: 'Option C', value: 'c' }]; menuItems = [{ icon: 'pi pi-pencil', label: 'Edit' }, { icon: 'pi pi-copy', label: 'Duplicate' }, { disabled: true, icon: 'pi pi-lock', label: 'Disabled item' }, { separator: true }, (0,_tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.dangerMenuItem)({ icon: 'pi pi-trash', label: 'Delete' })]; rows = [{ modality: 'CT', name: 'Sample study', series: 3 }, { modality: 'CT', name: 'Another study', series: 5 }, { modality: 'OT', name: 'Annotated export', series: 1 }]; selectedRow = this.rows[0]; drawerOpen = false; static ɵfac = function ThemePreviewPageComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ThemePreviewPageComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵdefineComponent"]({ type: ThemePreviewPageComponent, selectors: [["lib-theme-preview-page"]], hostAttrs: [1, "block", "h-full", "overflow-y-auto", "bg-surface-950", "text-color"], decls: 150, vars: 31, consts: [["contextMenu", ""], ["popover", ""], [1, "mx-auto", "max-w-5xl", "space-y-10", "p-8"], [1, "text-xl", "font-semibold"], [1, "text-muted-color", "mt-1", "text-sm"], [1, "bg-surface-800", "rounded", "px-1"], [1, "text-muted-color", "mb-2", "text-xs", "font-semibold", "tracking-wide", "uppercase"], [1, "flex", "flex-wrap", "gap-2"], [1, "border-surface-700", "rounded-md", "border", "px-2", "py-1"], [1, "flex", "flex-wrap", "items-center", "gap-3"], ["data-test-id", "theme-preview-p-button-primary", "label", "Primary"], ["data-test-id", "theme-preview-p-button-secondary", "label", "Secondary", "severity", "secondary"], ["data-test-id", "theme-preview-p-button-outlined", "label", "Outlined", "variant", "outlined"], ["data-test-id", "theme-preview-p-button-text", "label", "Text", 3, "text"], ["data-test-id", "theme-preview-p-button-danger", "label", "Danger", "severity", "danger"], ["data-test-id", "theme-preview-p-button-danger-outlined", "label", "Danger outlined", "severity", "danger", "variant", "outlined"], ["data-test-id", "theme-preview-p-button-contrast-outlined", "label", "Contrast outlined", "severity", "contrast", "variant", "outlined"], ["data-test-id", "theme-preview-p-button-plain-text", "label", "Plain text", "severity", "contrast", "plain", "", 3, "text"], ["data-test-id", "theme-preview-p-button-disabled", "label", "Disabled", 3, "disabled"], ["data-test-id", "theme-preview-p-button-tooltip", "label", "With tooltip", "severity", "secondary", "pTooltip", "Tooltip colors", "tooltipPosition", "top"], [1, "grid", "max-w-3xl", "grid-cols-2", "gap-4"], ["data-test-id", "theme-preview-input-filled", "pInputText", "", "placeholder", "Placeholder", 3, "formControl"], ["data-test-id", "theme-preview-input-empty", "pInputText", "", "placeholder", "Placeholder only", 3, "formControl"], ["data-test-id", "theme-preview-input-disabled", "pInputText", "", 3, "formControl"], ["data-test-id", "theme-preview-input-invalid", "pInputText", "", "placeholder", "Invalid state", 1, "ng-invalid", "ng-dirty", 3, "formControl"], ["data-test-id", "theme-preview-p-select-basic", "placeholder", "Select an option", "appendTo", "body", 3, "formControl", "options"], ["data-test-id", "theme-preview-p-multiselect-basic", "placeholder", "Multi select", "appendTo", "body", 3, "formControl", "options"], ["data-test-id", "theme-preview-p-datepicker-basic", "placeholder", "Pick a date", "appendTo", "body", 3, "formControl", "showIcon"], [1, "flex", "items-center", "gap-6"], [1, "flex", "items-center", "gap-2", "text-sm"], ["data-test-id", "theme-preview-p-checkbox-checked", 3, "formControl", "binary"], ["data-test-id", "theme-preview-p-checkbox-unchecked", 3, "formControl", "binary"], [1, "col-span-2", "max-w-md", "pt-2"], ["data-test-id", "theme-preview-p-slider-basic", 3, "formControl"], ["value", "0"], ["data-test-id", "theme-preview-p-tab-first", "value", "0"], ["data-test-id", "theme-preview-p-tab-second", "value", "1"], [1, "text-sm"], ["value", "1"], ["selectionMode", "single", "styleClass", "text-sm", 3, "selectionChange", "value", "selection"], ["pTemplate", "header"], ["pTemplate", "body"], [1, "text-muted-color", "mb-2", "text-xs"], ["data-test-id", "theme-preview-p-menu-example", "styleClass", "w-56", 3, "model"], ["data-test-id", "theme-preview-div-contextmenu-target", 1, "border-surface-700", "text-muted-color", "rounded-md", "border", "border-dashed", "px-4", "py-2", "text-sm", "select-none", 3, "contextmenu"], ["popup", "", "appendTo", "body", 3, "model"], ["data-test-id", "theme-preview-p-button-open-popover", "label", "Open popover", "severity", "secondary", 3, "click"], ["appendTo", "body"], [1, "w-64", "p-1", "text-sm"], [1, "font-semibold"], [1, "text-muted-color", "mt-1"], ["data-test-id", "theme-preview-p-button-open-drawer", "label", "Open drawer", "severity", "secondary", 3, "click"], ["header", "Drawer", 3, "drawerVisibleChange", "drawerVisible"], [1, "p-4", "text-sm"], ["value", "0", "data-test-id", "theme-preview-p-accordion-example"], ["data-test-id", "theme-preview-p-panel-example", 3, "showHeader"], [3, "panelSizes"], ["pTemplate", ""], [1, "flex", "flex-wrap", "items-center", "gap-4"], ["value", "Default"], ["value", "Secondary", "severity", "secondary"], ["value", "Success", "severity", "success"], ["value", "Warn", "severity", "warn"], ["value", "Danger", "severity", "danger"], ["styleClass", "h-2 w-40", 3, "value", "showValue"], ["width", "10rem", "height", "2rem"], [1, "mt-4", "flex", "flex-wrap", "gap-4", "text-sm"], [1, "text-(--p-app-status-success)"], [1, "text-(--p-app-status-danger)"], [1, "rounded", "bg-(--p-app-status-danger-background)", "px-2", "py-1"], [1, "rounded", "bg-(--p-app-phase-active-background)", "px-2", "py-1", "text-(--p-app-phase-active-color)"], [1, "w-28"], [1, "border-surface-700", "h-10", "rounded-md", "border"], [1, "text-muted-color", "mt-1", "truncate", "font-mono", "text-[10px]", 3, "title"], [1, "text-muted-color", "truncate", "font-mono", "text-[10px]", 3, "title"], [1, "font-mono", "text-xs"], ["pSortableColumn", "name"], ["field", "name"], [3, "pSelectableRow"], ["severity", "secondary", 3, "value"], [1, "flex", "h-full", "w-full", "items-center", "justify-center", "text-sm"]], template: function ThemePreviewPageComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](0, "div", 2)(1, "header")(2, "h1", 3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](3, "Theme preview"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](4, "p", 4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](5, " Every color below comes from a design token. To review a scheme, toggle the "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](6, "code", 5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](7, "dark"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](8, " class on "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](9, "code", 5); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](10, ""); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](11, " \u2014 nothing on this page may become unreadable. "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeaterCreate"](12, ThemePreviewPageComponent_For_13_Template, 6, 1, "section", null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](14, "section")(15, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](16, " Figma: dimension, focus, font "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](17, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeaterCreate"](18, ThemePreviewPageComponent_For_19_Template, 5, 3, "div", 8, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](20, "section")(21, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](22, "Buttons"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](23, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](24, "p-button", 10)(25, "p-button", 11)(26, "p-button", 12)(27, "p-button", 13)(28, "p-button", 14)(29, "p-button", 15)(30, "p-button", 16)(31, "p-button", 17)(32, "p-button", 18)(33, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](34, "section")(35, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](36, "Form fields"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](37, "div", 20); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](38, "input", 21)(39, "input", 22)(40, "input", 23)(41, "input", 24)(42, "p-select", 25)(43, "p-multiselect", 26)(44, "p-datepicker", 27); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](45, "div", 28)(46, "label", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](47, "p-checkbox", 30); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](48, " Checked "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](49, "label", 29); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](50, "p-checkbox", 31); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](51, " Unchecked "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](52, "div", 32); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](53, "p-slider", 33); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](54, "section")(55, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](56, "Tabs"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](57, "p-tabs", 34)(58, "p-tablist")(59, "p-tab", 35); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](60, "First tab"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](61, "p-tab", 36); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](62, "Second tab"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](63, "p-tabpanels")(64, "p-tabpanel", 34)(65, "p", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](66, "Tab panel content on the content background."); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](67, "p-tabpanel", 38)(68, "p", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](69, "Second panel."); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](70, "section")(71, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](72, "Table"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](73, "p-table", 39); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayListener"]("selectionChange", function ThemePreviewPageComponent_Template_p_table_selectionChange_73_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrestoreView"](_r1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayBindingSet"](ctx.selectedRow, $event) || (ctx.selectedRow = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplate"](74, ThemePreviewPageComponent_ng_template_74_Template, 8, 0, "ng-template", 40)(75, ThemePreviewPageComponent_ng_template_75_Template, 7, 4, "ng-template", 41); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](76, "section")(77, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](78, "Menu"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](79, "p", 42); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](80, " Hover/focus highlight must match every other openable overlay (context menus, selects): surface-800, selected options surface-700. "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](81, "p-menu", 43); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](82, "section")(83, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](84, " Context menu, popover, drawer "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](85, "div", 9)(86, "div", 44); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("contextmenu", function ThemePreviewPageComponent_Template_div_contextmenu_86_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrestoreView"](_r1); const contextMenu_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](89); return _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵresetView"](contextMenu_r6.show($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](87, " Right-click here for a context menu "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](88, "p-contextmenu", 45, 0); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](90, "p-button", 46); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ThemePreviewPageComponent_Template_p_button_click_90_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrestoreView"](_r1); const popover_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵreference"](92); return _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵresetView"](popover_r7.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](91, "p-popover", 47, 1)(93, "div", 48)(94, "p", 49); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](95, "Popover"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](96, "p", 50); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](97, " Overlay background, border, radius and gutter come from the preset. "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](98, "p-button", 51); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵlistener"]("click", function ThemePreviewPageComponent_Template_p_button_click_98_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵresetView"](ctx.drawerOpen = true); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](99, "lib-drawer", 52); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayListener"]("drawerVisibleChange", function ThemePreviewPageComponent_Template_lib_drawer_drawerVisibleChange_99_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵrestoreView"](_r1); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayBindingSet"](ctx.drawerOpen, $event) || (ctx.drawerOpen = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_21__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](100, "p", 53); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](101, "Drawer surface, border and text come from the preset."); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](102, "section")(103, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](104, "Accordion"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](105, "p-accordion", 54)(106, "p-accordion-panel", 34)(107, "p-accordion-header"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](108, "Expanded panel"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](109, "p-accordion-content")(110, "p", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](111, "Header, content and toggle-icon colors are stock Aura."); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](112, "p-accordion-panel", 38)(113, "p-accordion-header"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](114, "Collapsed panel"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](115, "p-accordion-content")(116, "p", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](117, "Second panel."); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](118, "section")(119, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](120, "Panel"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](121, "p-panel", 55)(122, "p", 37); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](123, " Headerless panel as used by the heading area: info-block background, subtle border, lg radius. "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](124, "section")(125, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](126, "Splitter"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](127, "p-splitter", 56); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtemplate"](128, ThemePreviewPageComponent_ng_template_128_Template, 2, 0, "ng-template", 57)(129, ThemePreviewPageComponent_ng_template_129_Template, 2, 0, "ng-template", 57); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](130, "section")(131, "h2", 6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](132, " Tags, progress, skeleton "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](133, "div", 58); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelement"](134, "p-tag", 59)(135, "p-tag", 60)(136, "p-tag", 61)(137, "p-tag", 62)(138, "p-tag", 63)(139, "p-progressbar", 64)(140, "p-skeleton", 65); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](141, "div", 66)(142, "span", 67); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](143, "Success text"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](144, "span", 68); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](145, "Danger text"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](146, "span", 69); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](147, "Danger surface"); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementStart"](148, "span", 70); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtext"](149, " Active phase "); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵelementEnd"]()()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeater"](ctx.tokenGroups); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵrepeater"](ctx.figmaScales); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](9); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("text", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("text", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("disabled", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.text); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.emptyText); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.disabledText); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.emptyText); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.select)("options", ctx.options); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.multi)("options", ctx.options); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.date)("showIcon", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.checked)("binary", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.unchecked)("binary", true); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("formControl", ctx.slider); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](20); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("value", ctx.rows); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayProperty"]("selection", ctx.selectedRow); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](8); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("model", ctx.menuItems); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("model", ctx.menuItems); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](11); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵtwoWayProperty"]("drawerVisible", ctx.drawerOpen); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](22); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("showHeader", false); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵstyleMap"](_angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction0"](29, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("panelSizes", _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵpureFunction0"](30, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵadvance"](12); _angular_core__WEBPACK_IMPORTED_MODULE_22__["ɵɵproperty"]("value", 60)("showValue", false); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_1__.AccordionModule, primeng_accordion__WEBPACK_IMPORTED_MODULE_1__.Accordion, primeng_api__WEBPACK_IMPORTED_MODULE_23__.PrimeTemplate, primeng_accordion__WEBPACK_IMPORTED_MODULE_1__.AccordionPanel, primeng_accordion__WEBPACK_IMPORTED_MODULE_1__.AccordionHeader, primeng_accordion__WEBPACK_IMPORTED_MODULE_1__.AccordionContent, primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, primeng_checkbox__WEBPACK_IMPORTED_MODULE_3__.CheckboxModule, primeng_checkbox__WEBPACK_IMPORTED_MODULE_3__.Checkbox, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_4__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_4__.ContextMenu, primeng_datepicker__WEBPACK_IMPORTED_MODULE_5__.DatePickerModule, primeng_datepicker__WEBPACK_IMPORTED_MODULE_5__.DatePicker, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.DrawerComponent, primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__.InputText, primeng_menu__WEBPACK_IMPORTED_MODULE_7__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_7__.Menu, primeng_multiselect__WEBPACK_IMPORTED_MODULE_8__.MultiSelectModule, primeng_multiselect__WEBPACK_IMPORTED_MODULE_8__.MultiSelect, primeng_panel__WEBPACK_IMPORTED_MODULE_9__.PanelModule, primeng_panel__WEBPACK_IMPORTED_MODULE_9__.Panel, primeng_popover__WEBPACK_IMPORTED_MODULE_10__.PopoverModule, primeng_popover__WEBPACK_IMPORTED_MODULE_10__.Popover, primeng_progressbar__WEBPACK_IMPORTED_MODULE_11__.ProgressBarModule, primeng_progressbar__WEBPACK_IMPORTED_MODULE_11__.ProgressBar, _angular_forms__WEBPACK_IMPORTED_MODULE_0__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_0__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_0__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_0__.FormControlDirective, primeng_select__WEBPACK_IMPORTED_MODULE_12__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_12__.Select, primeng_skeleton__WEBPACK_IMPORTED_MODULE_13__.SkeletonModule, primeng_skeleton__WEBPACK_IMPORTED_MODULE_13__.Skeleton, primeng_slider__WEBPACK_IMPORTED_MODULE_14__.SliderModule, primeng_slider__WEBPACK_IMPORTED_MODULE_14__.Slider, primeng_splitter__WEBPACK_IMPORTED_MODULE_15__.SplitterModule, primeng_splitter__WEBPACK_IMPORTED_MODULE_15__.Splitter, primeng_table__WEBPACK_IMPORTED_MODULE_16__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_16__.Table, primeng_table__WEBPACK_IMPORTED_MODULE_16__.SortableColumn, primeng_table__WEBPACK_IMPORTED_MODULE_16__.SelectableRow, primeng_table__WEBPACK_IMPORTED_MODULE_16__.SortIcon, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.TabsModule, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.Tabs, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.TabPanels, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.TabPanel, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.TabList, primeng_tabs__WEBPACK_IMPORTED_MODULE_17__.Tab, primeng_tag__WEBPACK_IMPORTED_MODULE_18__.TagModule, primeng_tag__WEBPACK_IMPORTED_MODULE_18__.Tag, primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_19__.Tooltip], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 75048 /*!***************************************************************!*\ !*** ./libs/feature/src/lib/tool-menu/tool-menu.component.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ToolMenuComponent: () => (/* binding */ ToolMenuComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../colors/colors.service */ 39298); /* harmony import */ var _create_object3d_dialog_create_object3d_dialog_component__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../create-object3d-dialog/create-object3d-dialog.component */ 7110); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _protocols__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../protocols */ 61632); /* harmony import */ var _relative_measurements_relative_measurement_dialog_relative_measurement_dialog_component__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../relative-measurements/relative-measurement-dialog/relative-measurement-dialog.component */ 52569); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["relativeMenu"]; const _c1 = ["object3dMenu"]; /* eslint-disable perfectionist/sort-objects */ const RELATIONSHIP_SPECS = { 'attached-point': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.POINT, isActive(annotations) { return annotations.length > 0; } }, 'curvature-point': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.POINT, isActive(annotations) { return annotations.some(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline)(annotation)); }, hasSeparator: true }, 'attached-distance': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.length > 0; } }, 'center-distance': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.length > 0; } }, chord: { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.some(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline)(annotation) || annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.ANGLE); } }, 'closest-distance-between-annotations': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.filter(annotation => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsObject3D)(annotation)).length >= 2; } }, 'closest-distance-to-one-annotation': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.some(annotation => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsPoint)(annotation)); } }, 'projected-distance': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.some(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline)(annotation)); } }, 'projected-distance-from-point': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE, isActive(annotations) { return annotations.some(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline)(annotation)) && annotations.some(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsPoint)(annotation)); }, hasSeparator: true }, 'angle-between-spline-axes': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.ANGLE, isActive(annotations) { return annotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsClosedSpline)(annotation)).length >= 2; } }, 'angle-between-splines': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.ANGLE, isActive(annotations) { return annotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsClosedSpline)(annotation)).length >= 2; }, hasSeparator: true }, 'attached-spline': { annotationType: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.OPEN_SPLINE, isActive(annotations) { return annotations.length > 0; } } }; /* eslint-enable perfectionist/sort-objects */ class ToolMenuComponent { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.AnnotationFacade); colorsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_14__.ColorsService); protocolCreation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_protocols__WEBPACK_IMPORTED_MODULE_17__.ProtocolCreationService); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_7__.DialogService); interactionModeService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_16__.InteractionModeService); object3DGeometryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.Object3DGeometryFacade); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_5__.TranslateService); viewportStoreInstance = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_10__.viewportStore); constructor() { // Plain DOM listener so unrelated keystrokes skip Angular change detection. globalThis.addEventListener('keydown', this.handleProtocolNavigation); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.DestroyRef).onDestroy(() => globalThis.removeEventListener('keydown', this.handleProtocolNavigation)); } relativeMenu = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('relativeMenu'); object3dMenu = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('object3dMenu'); currentLang = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)(this.translate.onLangChange, { initialValue: undefined }); object3dTypes = ['cylinder', 'hollow_cylinder', 'stl_file']; activeToolType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const beingCreated = this.annotationFacade.annotationBeingCreated(); const beingAddedTo = this.interactionModeService.annotationAddingPointsTo(); return beingCreated?.type ?? beingAddedTo?.type; }, ...(ngDevMode ? [{ debugName: "activeToolType" }] : [])); protocolProgress = this.protocolCreation.progress; activePlaceholder = this.protocolCreation.activePlaceholder; activePlaceholderFilled = this.protocolCreation.activePlaceholderFilled; relativeMeasurementsMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const annotations = this.annotationFacade.annotations(); const items = Object.entries(RELATIONSHIP_SPECS).flatMap(([type, { annotationType, isActive }]) => { const menuItem = { command: () => { this.openRelativeMeasurementDialog(type); }, disabled: !isActive(annotations), icon: annotationType, label: this.relationshipLabel(type) }; if (RELATIONSHIP_SPECS[type]?.hasSeparator) { return [menuItem, { separator: true }]; } return [menuItem]; }); return items; }, ...(ngDevMode ? [{ debugName: "relativeMeasurementsMenuItems" }] : [])); object3dMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { this.currentLang(); return this.object3dTypes.flatMap(type => { const item = { command: () => this.openCreateObject3DDialog(type), icon: 'object-3d', label: this.object3dTypeLabel(type) }; return type === 'stl_file' ? [{ separator: true }, item] : [item]; }); }, ...(ngDevMode ? [{ debugName: "object3dMenuItems" }] : [])); openRelativeMeasurementDialog(type) { this.dialogService.open(_relative_measurements_relative_measurement_dialog_relative_measurement_dialog_component__WEBPACK_IMPORTED_MODULE_18__.RelativeMeasurementDialogComponent, { closeOnEscape: true, header: 'Create ' + this.relationshipLabel(type), inputValues: { annotations: this.annotationFacade.annotations(), relationshipType: type }, modal: true, width: '400px' }); } openCreateObject3DMenu(event) { this.relativeMenu().hide(); this.object3dMenu().show(event); } openCreateObject3DDialog(type) { this.annotationFacade.deselectAllAnnotations(); const label = this.object3dTypeLabel(type); const dialog = this.dialogService.open(_create_object3d_dialog_create_object3d_dialog_component__WEBPACK_IMPORTED_MODULE_15__.CreateObject3DDialogComponent, { closeOnEscape: true, header: type === 'stl_file' ? label : `${this.translate.instant('createObject3d.create')} ${label}`, inputValues: { object3DType: type }, modal: true, width: '400px' }); dialog?.onClose.subscribe(result => { if (!result) return; this.handleObject3DCreation(result); }); } openRelativeMeasurementsMenu(event) { this.object3dMenu().hide(); this.relativeMenu().show(event); } cancelProtocol() { this.protocolCreation.cancelCurrentStep(); } setActiveToolType(toolType) { const existingNames = this.annotationFacade.annotations().map(ann => ann.name); switch (toolType) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.ANGLE: { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.angle)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Angle', existingNames), points: [] })); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.CLOSED_SPLINE: { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.closedSpline)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Closed Spline', existingNames), points: [] })); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.DISTANCE: { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.distance)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Distance', existingNames), points: [] })); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.OPEN_SPLINE: { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.openSpline)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Open Spline', existingNames), points: [] })); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationSourceType.POINT: { this.annotationFacade.creatingAnnotation((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.point)({ color: this.colorsService.currentColor(), hidden: true, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Point', existingNames), position: [Infinity, Infinity, Infinity] })); break; } default: { // Once we handle more tool types, this will only happen when setting `undefined` this.annotationFacade.cancelAnnotationCreation(); } } } startPlaceholder() { this.protocolCreation.handleCurrentPlaceholder(); } nextPlaceholder() { this.protocolCreation.goToNextPlaceholder(); } restartStep() { this.protocolCreation.restartCurrentStep(); } undo() { this.protocolCreation.undo(); } handleObject3DCreation(result) { const existingNames = this.annotationFacade.annotations().map(a => a.name); const color = this.colorsService.currentColor(); const crosshairPosition = this.viewportStoreInstance.intersection(); switch (result.object3DType) { case 'cylinder': { const annotation = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.cylinder)({ color, diameter: result.diameter, height: result.height, hidden: false, locked: result.locked, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Cylinder', existingNames), orientation: [0, 0, 0, 1], position: crosshairPosition, sides: 100 }); this.annotationFacade.addAnnotations(annotation); this.annotationFacade.selectAnnotations([annotation.id]); break; } case 'hollow_cylinder': { const annotation = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.hollowCylinder)({ color, height: result.height, hidden: false, innerDiameter: result.innerDiameter, locked: result.locked, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)('Hollow Cylinder', existingNames), orientation: [0, 0, 0, 1], outerDiameter: result.outerDiameter, position: crosshairPosition, sides: 100 }); this.annotationFacade.addAnnotations(annotation); this.annotationFacade.selectAnnotations([annotation.id]); break; } case 'stl_file': { this.handleStlImport(result); break; } } this.colorsService.nextColor(); } // Matched on event.code so the WASD aliases work on any keyboard layout. handleProtocolNavigation = event => { switch (event.code) { case 'ArrowLeft': case 'KeyA': { if (!this.validateKeyboardEvent(event)) return; this.handleProtocolBack(); break; } case 'ArrowRight': case 'KeyD': { if (!this.validateKeyboardEvent(event)) return; this.handleProtocolForward(); break; } } }; handleProtocolBack() { // Skip if no active placeholder if (!this.protocolCreation.activePlaceholder()) { return; } // If in the confirmation phase, restart step if (this.protocolCreation.activePlaceholderFilled()) { this.restartStep(); return; } // If in the preparation phase, go back a step (undo) if (this.activeToolType() === undefined) { this.undo(); } } handleProtocolForward() { // Skip if no active placeholder if (!this.protocolCreation.activePlaceholder()) { return; } // If in the confirmation phase, complete step if (this.protocolCreation.activePlaceholderFilled()) { this.nextPlaceholder(); return; } // If in the preparation phase, start creation if (this.activeToolType() === undefined) { this.startPlaceholder(); } } relationshipLabel(type) { return this.translate.instant(`annotationMenu.relativeMeasurements.${(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.toCamelCase)(type)}`); } object3dTypeLabel(type) { return this.translate.instant(`createObject3d.types.${(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.toCamelCase)(type)}`); } handleStlImport(result) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!result.stlData) return; const existingNames = _this.annotationFacade.annotations().map(a => a.name); const color = _this.colorsService.currentColor(); const crosshairPosition = _this.viewportStoreInstance.intersection(); let { vertices } = result.stlData; const { centroid, fileName, normals } = result.stlData; let axisOfSymmetryRotation = [...gl_matrix__WEBPACK_IMPORTED_MODULE_6__.create()]; // A segmentation mesh is already in patient space: import it at its // embedded coordinates instead of dropping it at the crosshair, and lock // it so it cannot drift out of alignment with the volume. const isSegmentation = result.stlImportMode === 'segmentation'; if (!isSegmentation) { const aligned = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.autoAlignAxis)(vertices, centroid); vertices = aligned.alignedVertices; axisOfSymmetryRotation = aligned.rotationMatrix; } const baseName = fileName.replace(/\.stl$/i, ''); const geometry = { centroid: [...centroid], indices: new Uint32Array(0), normals, vertices }; const geometryId = `stl:${yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.hashObject3DGeometry)(geometry)}`; const annotation = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.stlObject3D)({ autoAlignAxis: !isSegmentation, axisOfSymmetryRotation, centerOfRotation: [...centroid], color, fileName, geometryId, hidden: false, locked: isSegmentation, name: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.incrementName)(baseName, existingNames, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.ANNOTATION_NAME_MAX_LENGTH), orientation: [0, 0, 0, 1], position: isSegmentation ? [...centroid] : crosshairPosition }); _this.object3DGeometryFacade.setStlGeometry(annotation.id, geometryId, geometry); _this.annotationFacade.addAnnotations(annotation); _this.annotationFacade.selectAnnotations([annotation.id]); })(); } validateKeyboardEvent(event) { if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) return false; if (event.repeat) return false; if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_12__.isEditableTarget)(event.target)) return false; return true; } static ɵfac = function ToolMenuComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ToolMenuComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵdefineComponent"]({ type: ToolMenuComponent, selectors: [["lib-tool-menu"]], viewQuery: function ToolMenuComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵviewQuerySignal"](ctx.relativeMenu, _c0, 5)(ctx.object3dMenu, _c1, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵqueryAdvance"](2); } }, decls: 5, vars: 6, consts: [["relativeMenu", ""], ["object3dMenu", ""], [3, "toolChanged", "createObject3DClicked", "openRelativeMeasurements", "startPlaceholder", "placeholderComplete", "protocolCancelled", "stepRestarted", "undoPlaceholder", "activeTool", "activePlaceholder", "activePlaceholderFilled", "protocolProgress"], [3, "model"]], template: function ToolMenuComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementStart"](0, "lib-toolbar", 2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵlistener"]("toolChanged", function ToolMenuComponent_Template_lib_toolbar_toolChanged_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.setActiveToolType($event)); })("createObject3DClicked", function ToolMenuComponent_Template_lib_toolbar_createObject3DClicked_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.openCreateObject3DMenu($event)); })("openRelativeMeasurements", function ToolMenuComponent_Template_lib_toolbar_openRelativeMeasurements_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.openRelativeMeasurementsMenu($event)); })("startPlaceholder", function ToolMenuComponent_Template_lib_toolbar_startPlaceholder_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.startPlaceholder()); })("placeholderComplete", function ToolMenuComponent_Template_lib_toolbar_placeholderComplete_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.nextPlaceholder()); })("protocolCancelled", function ToolMenuComponent_Template_lib_toolbar_protocolCancelled_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.cancelProtocol()); })("stepRestarted", function ToolMenuComponent_Template_lib_toolbar_stepRestarted_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.restartStep()); })("undoPlaceholder", function ToolMenuComponent_Template_lib_toolbar_undoPlaceholder_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.undo()); }); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵelement"](1, "lib-annotation-menu", 3, 0)(3, "lib-annotation-menu", 3, 1); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("activeTool", ctx.activeToolType())("activePlaceholder", ctx.activePlaceholder())("activePlaceholderFilled", ctx.activePlaceholderFilled())("protocolProgress", ctx.protocolProgress()); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("model", ctx.relativeMeasurementsMenuItems()); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_19__["ɵɵproperty"]("model", ctx.object3dMenuItems()); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_11__.ToolbarComponent, _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_13__.AnnotationMenuComponent], encapsulation: 2 }); } /***/ }, /***/ 71202 /*!*************************************************************************!*\ !*** ./libs/feature/src/lib/top-navigation/top-navigation.component.ts ***! \*************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TopNavigationComponent: () => (/* binding */ TopNavigationComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 13333); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 69042); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 13329); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_avatar__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/avatar */ 30430); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _dicom_importer_components_export_to_store_dialog_export_to_store_dialog_component__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../dicom-importer/components/export-to-store-dialog/export-to-store-dialog.component */ 26133); /* harmony import */ var _work_session_nav_work_session_nav_component__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../work-session-nav/work-session-nav.component */ 76774); /* harmony import */ var _work_session_work_session_import_service__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../work-session/work-session-import.service */ 50784); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ root: "gap-1.5 px-3.5 py-1.5" }); const _c1 = () => ({ root: "h-9 w-9 p-0" }); function TopNavigationComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵlistener"]("click", function TopNavigationComponent_Conditional_10_Template_p_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); const navMenu_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreference"](32); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](navMenu_r4.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](3, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](4, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](2, 2, "topNavigation.navMenu.workSession"), " "); } } function TopNavigationComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-work-session-nav", 13); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); const workSessionUid_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreadContextLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("activeWorkSessionUid", workSessionUid_r5); } } function TopNavigationComponent_ng_template_17_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-icon", 22); } } function TopNavigationComponent_ng_template_21_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-icon", 23); } } function TopNavigationComponent_ng_template_25_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-icon", 24); } } function TopNavigationComponent_ng_template_29_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-menu-item", 25); } if (rf & 2) { const item_r7 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("item", item_r7); } } function TopNavigationComponent_ng_template_33_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-menu-item", 25); } if (rf & 2) { const item_r8 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("item", item_r8); } } function TopNavigationComponent_ng_template_37_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "lib-menu-item", 25); } if (rf & 2) { const item_r9 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("item", item_r9); } } // TODO: restore after the Montreal Imaging Symposium. const SHOW_ANALYSIS_FILE_IO = false; const LIFE_BY_SEVERITY = { error: 5000, info: 3000, success: 3000, warn: 4000 }; class TopNavigationComponent { authService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.AuthService); workSessionNavService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.WorkSessionNavigationService); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_17__.DialogService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_14__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_13__.TranslateService); workSessionImportService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_work_session_work_session_import_service__WEBPACK_IMPORTED_MODULE_24__.WorkSessionImportService); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_5__.Router); db = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.DicomDatabaseService); preferences = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.PreferencesService); recentWorkSessions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.RecentWorkSessionsService); recentSessions = this.recentWorkSessions.sessions; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const parameters = this.childParams(); const storeUid = parameters.get('storeUid'); const studyUid = parameters.get('studyUid'); const seriesUid = parameters.get('seriesUid'); const workSessionUid = parameters.get('workSessionUid'); if (!storeUid || !studyUid || !seriesUid || !workSessionUid) return; if (workSessionUid === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_21__.WORK_SESSION_NEW_KEY) return; this.recentWorkSessions.record({ seriesUid, storeUid, studyUid, workSessionUid }); }); } currentLang = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)((0,rxjs__WEBPACK_IMPORTED_MODULE_6__.merge)(this.translate.onLangChange, this.translate.onTranslationChange), { initialValue: undefined }); childParams = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)(this.router.events.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.filter)(event => event instanceof _angular_router__WEBPACK_IMPORTED_MODULE_5__.NavigationEnd), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(() => { let route = this.router.routerState.root; while (route.firstChild) { route = route.firstChild; } return route.snapshot.paramMap; })), { initialValue: (() => { let route = this.router.routerState.root; while (route.firstChild) { route = route.firstChild; } return route.snapshot?.paramMap ?? (0,_angular_router__WEBPACK_IMPORTED_MODULE_5__.convertToParamMap)({}); })() }); seriesFullyCached = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toObservable)(this.childParams).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(parameters => ({ seriesUid: parameters.get('seriesUid'), storeUid: parameters.get('storeUid') })), (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.switchMap)(({ seriesUid, storeUid }) => seriesUid && storeUid ? this.db.streamSeriesCacheProgress(seriesUid, storeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.isSeriesFullyCached), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.of)(false))) : (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.of)(false))), { initialValue: false }); currentUrl = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)(this.router.events.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.filter)(event => event instanceof _angular_router__WEBPACK_IMPORTED_MODULE_5__.NavigationEnd), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.map)(() => this.router.url)), { initialValue: this.router.url }); workspaceMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { this.currentLang(); const url = this.currentUrl(); const libraryClass = url.startsWith('/library') ? 'text-primary-400' : undefined; const analysesClass = url.startsWith('/analyses') ? 'text-primary-400' : undefined; return [{ command: () => this.router.navigate(['/library']), icon: 'images', iconClass: libraryClass, label: this.translate.instant('topNavigation.workspaceMenu.imagingLibrary'), labelClass: libraryClass }, { command: () => this.router.navigate(['/analyses']), icon: 'desktop', iconClass: analysesClass, label: this.translate.instant('topNavigation.workspaceMenu.liveAnalyses'), labelClass: analysesClass }]; }, ...(ngDevMode ? [{ debugName: "workspaceMenuItems" }] : [])); navMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { this.currentLang(); const hasWorkSession = !!this.childParams().get('workSessionUid'); return [...(SHOW_ANALYSIS_FILE_IO ? [{ command: () => this.workSessionImportService.import(), icon: 'folder-open', label: this.translate.instant('topNavigation.navMenu.openWorkSession') }] : []), { command: () => this.workSessionNavService.save(), disabled: !hasWorkSession, icon: 'save', label: this.translate.instant('topNavigation.navMenu.saveWorkSession') }, ...(SHOW_ANALYSIS_FILE_IO ? [{ command: () => this.workSessionNavService.export(), disabled: !hasWorkSession, icon: 'download', label: this.translate.instant('topNavigation.navMenu.exportWorkSession') }] : []), { command: () => this.openExportToDicomStore(), disabled: !this.childParams().get('seriesUid') || !this.seriesFullyCached(), icon: 'share', label: this.translate.instant('topNavigation.navMenu.archiveAsDicom') }]; }, ...(ngDevMode ? [{ debugName: "navMenuItems" }] : [])); userMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { var _this = this; this.currentLang(); return [{ command: function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // Sign-out wipes the local database; edits still in the autosave // debounce or an unfinished push would be lost without this. yield _this.workSessionNavService.flushPendingChanges(); yield _this.authService.logout(); _this.messageService.add({ life: 3000, severity: 'info', summary: _this.translate.instant('topNavigation.userMenu.signedOut') }); }); return function command() { return _ref.apply(this, arguments); }; }(), icon: 'sign-out', label: this.translate.instant('topNavigation.userMenu.signOut') }]; }, ...(ngDevMode ? [{ debugName: "userMenuItems" }] : [])); leafQueryParams() { let route = this.router.routerState.root; while (route.firstChild) route = route.firstChild; return route.snapshot.queryParamMap.get('otSeriesUid'); } openExportToDicomStore() { const seriesUid = this.childParams().get('seriesUid'); if (!seriesUid) return; const data = { defaultStoreUid: this.preferences.get().storeUid ?? this.childParams().get('storeUid') ?? undefined, existingOtSeriesUid: this.leafQueryParams() ?? undefined, seriesUids: [seriesUid], storeUid: this.childParams().get('storeUid') ?? undefined, studyUid: this.childParams().get('studyUid') ?? undefined, workSessionUid: this.childParams().get('workSessionUid') ?? undefined }; const reference = this.dialogService.open(_dicom_importer_components_export_to_store_dialog_export_to_store_dialog_component__WEBPACK_IMPORTED_MODULE_22__.ExportToStoreDialogComponent, { closable: true, data, header: this.translate.instant('topNavigation.navMenu.archiveAsDicom'), width: '28rem' }); reference?.onClose.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_12__.take)(1)).subscribe(outcome => { if (!outcome) return; this.messageService.add({ ...(outcome.detail ? { detail: outcome.detail } : {}), life: LIFE_BY_SEVERITY[outcome.severity], severity: outcome.severity, summary: this.translate.instant(outcome.messageKey) }); }); } static ɵfac = function TopNavigationComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TopNavigationComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵdefineComponent"]({ type: TopNavigationComponent, selectors: [["lib-top-navigation"]], features: [_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵProvidersFeature"]([_work_session_work_session_import_service__WEBPACK_IMPORTED_MODULE_24__.WorkSessionImportService])], decls: 39, vars: 35, consts: [["icon", ""], ["workspaceMenu", ""], ["item", ""], ["navMenu", ""], ["userMenu", ""], [1, "border-surface-800", "flex", "h-14", "shrink-0", "items-stretch", "gap-3", "border-b", "bg-(--p-app-chrome-app-header)", "pr-4", "pl-3", "text-sm", "select-none", 3, "aria-label"], [1, "flex", "shrink-0", "items-center", "gap-3"], ["data-test-id", "top-navigation-a-home-link", "href", "#", 1, "mx-2", "flex", "items-center", 3, "aria-label"], ["ngSrc", "assets/svg/logo.svg", "width", "36", "height", "36", "alt", "Logo", "priority", "", 1, "size-9"], ["data-test-id", "top-navigation-p-button-workspace", "outlined", "", "size", "small", "severity", "contrast", 3, "click", "pt"], ["icon", "angle-down", "iconClass", "text-muted-color text-xs"], ["data-test-id", "top-navigation-p-button-work-session-", "outlined", "", "size", "small", "severity", "contrast", 3, "pt"], [1, "flex", "min-w-0", "flex-1"], [1, "flex", "w-full", "min-w-0", 3, "activeWorkSessionUid"], [1, "flex", "shrink-0", "items-center", "gap-1"], ["data-test-id", "top-navigation-p-button-search", "text", "", "plain", "", "severity", "contrast", 3, "ariaLabel", "pt"], ["data-test-id", "top-navigation-p-button-notifications", "text", "", "plain", "", "severity", "contrast", 3, "ariaLabel", "pt"], ["data-test-id", "top-navigation-p-button-user-menu", "text", "", "plain", "", "severity", "contrast", 3, "onClick", "ariaLabel", "pt"], ["data-test-id", "top-navigation-p-menu-workspace", "popup", "", 3, "model"], ["data-test-id", "top-navigation-p-menu-navigation", "popup", "", 3, "model"], ["data-test-id", "top-navigation-p-menu-user", 3, "model", "popup"], ["data-test-id", "top-navigation-p-button-work-session-", "outlined", "", "size", "small", "severity", "contrast", 3, "click", "pt"], ["icon", "search", 1, "text-lg"], ["icon", "bell", 1, "text-lg"], ["icon", "user-circle", 1, "size-(--p-app-icon-size-md)"], [3, "item"]], template: function TopNavigationComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "nav", 5); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](2, "div", 6)(3, "a", 7); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](5, "img", 8); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](6, "p-button", 9); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵlistener"]("click", function TopNavigationComponent_Template_p_button_click_6_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const workspaceMenu_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreference"](28); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](workspaceMenu_r2.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](8, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](9, "lib-icon", 10); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditionalCreate"](10, TopNavigationComponent_Conditional_10_Template, 4, 5, "p-button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](11, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵdeclareLet"](12); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditionalCreate"](13, TopNavigationComponent_Conditional_13_Template, 1, 1, "lib-work-session-nav", 13); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](14, "div", 14)(15, "p-button", 15); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](16, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](17, TopNavigationComponent_ng_template_17_Template, 1, 0, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](19, "p-button", 16); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](20, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](21, TopNavigationComponent_ng_template_21_Template, 1, 0, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](23, "p-button", 17); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](24, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵlistener"]("onClick", function TopNavigationComponent_Template_p_button_onClick_23_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const userMenu_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreference"](36); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](userMenu_r6.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](25, TopNavigationComponent_ng_template_25_Template, 1, 0, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](27, "p-menu", 18, 1); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](29, TopNavigationComponent_ng_template_29_Template, 1, 1, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](31, "p-menu", 19, 3); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](33, TopNavigationComponent_ng_template_33_Template, 1, 1, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](35, "p-menu", 20, 4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](37, TopNavigationComponent_ng_template_37_Template, 1, 1, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵariaProperty"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵinterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](1, 18, "topNavigation.navMenu.homeAriaLabel"))); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵariaProperty"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵinterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](4, 20, "topNavigation.navMenu.homeLabel"))); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](31, _c0)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](8, 22, "topNavigation.navMenu.workspace"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditional"](ctx.childParams().get("seriesUid") ? 10 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵstoreLet"](ctx.childParams().get("workSessionUid") ?? undefined); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditional"](ctx.recentSessions().length > 0 ? 13 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](16, 25, "topNavigation.navMenu.searchAriaLabel"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](32, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](20, 27, "topNavigation.navMenu.notificationsAriaLabel"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](33, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](24, 29, "topNavigation.navMenu.userMenuAriaLabel"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](34, _c1)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("model", ctx.workspaceMenuItems()); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("model", ctx.navMenuItems()); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("model", ctx.userMenuItems())("popup", true); } }, dependencies: [primeng_avatar__WEBPACK_IMPORTED_MODULE_15__.AvatarModule, primeng_button__WEBPACK_IMPORTED_MODULE_16__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_16__.Button, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.IconComponent, primeng_menu__WEBPACK_IMPORTED_MODULE_18__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_18__.Menu, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_20__.MenuItemComponent, _work_session_nav_work_session_nav_component__WEBPACK_IMPORTED_MODULE_23__.WorkSessionNavComponent, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgOptimizedImage, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_13__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 12100 /*!*******************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-actors.service.ts ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationActorsService: () => (/* binding */ AnnotationActorsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_post_process__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/post-process */ 16352); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../viewport-interaction/viewport-interaction.service */ 46184); /* harmony import */ var _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../window-details/window-details.service */ 99360); /* harmony import */ var _annotation_updaters_angle_updater__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./annotation-updaters/angle-updater */ 59985); /* harmony import */ var _annotation_updaters_distance_updater__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./annotation-updaters/distance-updater */ 44967); /* harmony import */ var _annotation_updaters_object3d_updater__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./annotation-updaters/object3d-updater */ 50980); /* harmony import */ var _annotation_updaters_point_updater__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./annotation-updaters/point-updater */ 4800); /* harmony import */ var _annotation_updaters_spline_updater__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./annotation-updaters/spline-updater */ 62781); /** * This service listens for updates from the `AnnotationFacade`, * and ensures each annotation has a corresponding `AnnotationUpdater` instance * which is called as relevant changes are made. * * It also keeps references to active viewports so that renders can be triggered * on relevant updates. */ class AnnotationActorsService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.AnnotationFacade); interactionModeService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_9__.InteractionModeService); engine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.RenderingEngineService); renderSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.renderSettingsStore); viewportStoreInstance = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.viewportStore); object3DGeometryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.Object3DGeometryFacade); viewports = []; latestFadeCameras = {}; updaterLookup = new Map(); clippingRangeOverrides = new Map(); mouseWorldPosition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_10__.ViewportInteractionService).mouseWorldPosition; hoveredAnnotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_10__.ViewportInteractionService).hoveredAnnotation; dragDetails = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_10__.ViewportInteractionService).dragDetails; devicePixelRatio = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_window_details_window_details_service__WEBPACK_IMPORTED_MODULE_11__.WindowDetailsService).devicePixelRatio; annotationSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { return this.annotationFacade.annotationSize() / this.devicePixelRatio(); }, ...(ngDevMode ? [{ debugName: "annotationSize" }] : [])); // Include the annotation currently being created so we can render it, // but not include it in the proper collection until it is complete. annotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const annotations = this.annotationFacade.annotations(); const beingCreated = this.annotationFacade.annotationBeingCreated(); if (beingCreated !== undefined) { return [...annotations, beingCreated]; } return annotations; }, ...(ngDevMode ? [{ debugName: "annotations" }] : [])); effectsReady = false; initEffects() { if (this.effectsReady) return; (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.assertInInjectionContext)(this.initEffects); // Handle changes to any annotations in the store const updateHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const annotations = this.annotations(); const usedIds = []; for (const annotation of annotations) { if (!annotation.hidden && (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_6__.isRenderable)(annotation)) { // Update Item here this.updateAnnotationActors(annotation); usedIds.push(annotation.id); } } this.cleanupEntries(usedIds); this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "updateHandler" }] : [])); // By moving this to a separate effect, we don't have to // update every item on each render unless the selection changes const selectHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const selectedAnnotations = this.annotationFacade.selectedAnnotations(); const interactionMode = this.interactionModeService.interactionMode(); for (const updater of this.updaterLookup.values()) { if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.ADD_POINTS && interactionMode.annotationId === updater.annotation.id) { updater.setInteractionState(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.ADDING_POINTS); } else if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.CREATE && interactionMode.annotation.id === updater.annotation.id) { updater.setInteractionState(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.BEING_CREATED); } else if (selectedAnnotations.includes(updater.annotation)) { updater.setInteractionState(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.SELECTED); } else { updater.setInteractionState(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.DESELECTED); } } // Tell the screen-space outline pass which Object3D annotations are // selected. The pass filters by `outlinable` flag on each actor. const outlineIds = new Set(); for (const annotation of selectedAnnotations) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsObject3D)(annotation)) outlineIds.add(annotation.id); } for (const pass of this.engine.getPostProcessPassesById(_tomoverse_post_process__WEBPACK_IMPORTED_MODULE_5__.OUTLINE_PASS_ID)) { pass.setSelectedAnnotationIds(outlineIds); } // On the VOLUME_3D viewport, new control-point actors are created with // generic lighting values from applyAnnotationLighting. refreshLighting() // applies the lit material used for every VR preset without waiting for the // next zoom to trigger refreshForViewportScaleChange. this.refreshLighting(); this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "selectHandler" }] : [])); // Separate handler for mouse position change as well, because this happens // often and usually doesn't affect most annotations const mouseMoveHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const mousePosition = this.mouseWorldPosition(); const interactionMode = this.interactionModeService.interactionMode(); let activeAnnotationId; switch (interactionMode.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.ADD_POINTS: { activeAnnotationId = interactionMode.annotationId; break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.CREATE: { activeAnnotationId = interactionMode.annotation.id; break; } } for (const updater of this.updaterLookup.values()) { // Right now only annotations being created will use this if (updater.annotation.id === activeAnnotationId) { updater.setMouseWorldPosition(mousePosition); break; } } this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "mouseMoveHandler" }] : [])); // Though this iterates through everything, most updaters will // ignore the `setIsHovered` calls because the value won't change const hoverHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const hoverDetails = this.hoveredAnnotation(); const dragDetails = this.dragDetails(); for (const updater of this.updaterLookup.values()) { let isHovered = false; let pointIndex; // Drag takes precedence if (dragDetails.annotationId) { isHovered = dragDetails.annotationId === updater.annotation.id; pointIndex = dragDetails.pointIndex; } else { isHovered = hoverDetails?.annotationId === updater.annotation.id; pointIndex = hoverDetails?.pointIndex; } updater.setIsHovered(isHovered, pointIndex); } this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "hoverHandler" }] : [])); // Re-push fade uniforms to each updater whenever a viewport camera // changes. Source of truth is the viewport store rather than // viewport.getCamera() because the store is updated first and the // Cornerstone viewport catches up afterwards. const fadeCameraHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const cameras = this.viewportStoreInstance.viewportCameras(); const byViewportId = {}; for (const [axisState, details] of Object.entries(cameras)) { byViewportId[axisState] = { focalPoint: details.focalPoint, position: details.position, viewPlaneNormal: details.viewPlaneNormal }; } this.latestFadeCameras = byViewportId; for (const updater of this.updaterLookup.values()) { updater.refreshFade(byViewportId); } this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "fadeCameraHandler" }] : [])); const annotationSizeHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const annotationSize = this.annotationSize(); for (const updater of this.updaterLookup.values()) { updater.setAnnotationSize(annotationSize); } this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "annotationSizeHandler" }] : [])); //Without this, switching ENDO <-> X-ray leaves the 3d object's lighting // state stale until the next signal that re-runs the annotations effect. const lightingPresetHandler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const projectionMode = (0,_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.isProjectionPreset)(this.renderSettings.volumeSettings().selectedPreset); for (const updater of this.updaterLookup.values()) { updater.setProjectionMode(projectionMode); } this.refreshLighting(); this.renderViewports(); }, ...(ngDevMode ? [{ debugName: "lightingPresetHandler" }] : [])); // Destroy effects, otherwise this service can't be garbage collected (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { updateHandler.destroy(); selectHandler.destroy(); mouseMoveHandler.destroy(); hoverHandler.destroy(); // Unsubscribe camera observers installed by `syncClippingRangeOverrides`. for (const restore of this.clippingRangeOverrides.values()) restore(); this.clippingRangeOverrides.clear(); fadeCameraHandler.destroy(); annotationSizeHandler.destroy(); lightingPresetHandler.destroy(); }); this.effectsReady = true; } setViewports(viewports) { const removedViewports = this.viewports.filter(vp => !viewports.includes(vp)); this.viewports = viewports; for (const updater of this.updaterLookup.values()) { updater.setViewports(viewports); } // Tear down overlay renderers for viewports that are no longer active. // Updaters already removed their actors in the setViewports call above. for (const viewport of removedViewports) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.detachAnnotationOverlay)(viewport); } // Cornerstone re-tiles its offscreen canvas whenever the active viewport // set changes, so every remaining overlay needs its sub-rect re-synced. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.resyncAnnotationOverlayViewports)(viewports); this.syncClippingRangeOverrides(); this.renderViewports(); } refreshForViewportScaleChange() { for (const updater of this.updaterLookup.values()) { updater.setViewports(this.viewports); } this.refreshLighting(); this.renderViewports(); } refreshLighting() { const renderMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(() => this.renderSettings.volumeSettings().selectedPreset); for (const viewport of this.viewports) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.applyAnnotationActorLighting)(viewport.id, viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportType.VOLUME_3D ? renderMode : undefined); } } /** * Pins a wide [-9999, 9999] clipping range on each VolumeViewport3D camera * whenever an Object3D annotation is tracked. Object3D actors are excluded * from scene bounds, so Cornerstone's auto-computed near/far would z-clip * geometry extending past the volume. Hooks `Modified()` directly because * Cornerstone suppresses the DOM CAMERA_MODIFIED event. */ syncClippingRangeOverrides() { const currentIds = new Set(this.viewports.map(viewport => viewport.id)); for (const [id, restore] of this.clippingRangeOverrides) { if (!currentIds.has(id)) { restore(); this.clippingRangeOverrides.delete(id); } } for (const viewport of this.viewports) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportType.VOLUME_3D) continue; if (this.clippingRangeOverrides.has(viewport.id)) continue; const camera = viewport.getRenderer().getActiveCamera(); let pinning = false; const subscription = camera.onModified(() => { // Guard against our own `setClippingRange` re-triggering Modified(). if (pinning) return; if (!this.hasObject3DUpdater()) return; const [near, far] = camera.getClippingRange(); if (near === -9999 && far === 9999) return; pinning = true; try { camera.setClippingRange(-9999, 9999); } finally { pinning = false; } }); this.clippingRangeOverrides.set(viewport.id, () => subscription.unsubscribe()); } } renderViewports() { this.viewports = this.viewports.filter(engine => !engine.isDisabled); this.engine.renderAll(); } hasObject3DUpdater() { for (const updater of this.updaterLookup.values()) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsObject3D)(updater.annotation)) return true; } return false; } updateAnnotationActors(annotation) { const updater = this.updaterLookup.get(annotation.id); if (updater === undefined) { const newUpdater = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(() => this.createUpdater(annotation)); if (newUpdater) { newUpdater.refreshFade(this.latestFadeCameras); newUpdater.setProjectionMode((0,_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.isProjectionPreset)((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(() => this.renderSettings.volumeSettings().selectedPreset))); this.updaterLookup.set(annotation.id, newUpdater); } } else { updater.update(annotation); } } createUpdater(annotation) { // If an annotation is currently being created, it is also considered selected // for display purposes. const interactionState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(() => { const selectedAnnotations = this.annotationFacade.selectedAnnotations(); const interactionMode = this.interactionModeService.interactionMode(); if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.ADD_POINTS && interactionMode.annotationId === annotation.id) { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.ADDING_POINTS; } if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType.CREATE && interactionMode.annotation.id === annotation.id) { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.BEING_CREATED; } if (selectedAnnotations.includes(annotation)) { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.SELECTED; } return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationInteractionState.DESELECTED; }); switch (annotation.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.ANGLE: { return new _annotation_updaters_angle_updater__WEBPACK_IMPORTED_MODULE_12__.AngleUpdater(annotation, this.viewports, interactionState, this.annotationSize()); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.CLOSED_SPLINE: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.OPEN_SPLINE: { return new _annotation_updaters_spline_updater__WEBPACK_IMPORTED_MODULE_16__.SplineUpdater(annotation, this.viewports, interactionState, this.annotationSize()); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.CYLINDER: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.HOLLOW_CYLINDER: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.STL: { return this.createObject3DUpdater(annotation, interactionState); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.DISTANCE: { return new _annotation_updaters_distance_updater__WEBPACK_IMPORTED_MODULE_13__.DistanceUpdater(annotation, this.viewports, interactionState, this.annotationSize()); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.POINT: { return new _annotation_updaters_point_updater__WEBPACK_IMPORTED_MODULE_15__.PointUpdater(annotation, this.viewports, interactionState, this.annotationSize()); } default: { return; } } } createObject3DUpdater(annotation, interactionState) { if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsObject3D)(annotation)) return; const geometry = this.object3DGeometryFacade.getGeometry(annotation.id); if (!geometry) return; return new _annotation_updaters_object3d_updater__WEBPACK_IMPORTED_MODULE_14__.Object3DUpdater(annotation, this.viewports, interactionState, geometry, this.annotationSize()); } cleanupEntries(idsToKeep) { for (const key of this.updaterLookup.keys()) { if (!idsToKeep.includes(key)) { this.updaterLookup.get(key)?.cleanup(); this.updaterLookup.delete(key); } } } static ɵfac = function AnnotationActorsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationActorsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AnnotationActorsService, factory: AnnotationActorsService.ɵfac }); } /***/ }, /***/ 75939 /*!****************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-fade-shader.ts ***! \****************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CAMERA_DEC_TOKEN: () => (/* binding */ CAMERA_DEC_TOKEN), /* harmony export */ LIGHT_IMPL_TOKEN: () => (/* binding */ LIGHT_IMPL_TOKEN), /* harmony export */ POSITION_VC_DEC_TOKEN: () => (/* binding */ POSITION_VC_DEC_TOKEN), /* harmony export */ POSITION_VC_IMPL_TOKEN: () => (/* binding */ POSITION_VC_IMPL_TOKEN), /* harmony export */ applyAnnotationFade: () => (/* binding */ applyAnnotationFade), /* harmony export */ applyFadeShader: () => (/* binding */ applyFadeShader) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _shaders_annotation_fade_decl_frag_glsl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/annotation-fade-decl.frag.glsl */ 68105); /* harmony import */ var _shaders_annotation_fade_decl_vert_glsl__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/annotation-fade-decl.vert.glsl */ 22926); /* harmony import */ var _shaders_annotation_fade_impl_frag_glsl__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./shaders/annotation-fade-impl.frag.glsl */ 50927); /* harmony import */ var _shaders_annotation_fade_impl_vert_glsl__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./shaders/annotation-fade-impl.vert.glsl */ 6504); const ANNOTATION_FADE_FEATURE = 'annotation-fade'; // vtk template placeholders we splice into. Each must match a token vtk.js // emits in its shipped vtkPolyDataVS / vtkPolyDataFS shaders byte-for-byte // or the corresponding String.replace silently no-ops. Exported so a test // can verify they still appear in vtk.js's shipped poly-data shaders. const CAMERA_DEC_TOKEN = '//VTK::Camera::Dec'; const POSITION_VC_IMPL_TOKEN = '//VTK::PositionVC::Impl'; const POSITION_VC_DEC_TOKEN = '//VTK::PositionVC::Dec'; const LIGHT_IMPL_TOKEN = '//VTK::Light::Impl'; const parametersByMapper = new WeakMap(); const REPLACEMENTS = [(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vertexReplacement)(CAMERA_DEC_TOKEN, [CAMERA_DEC_TOKEN, _shaders_annotation_fade_decl_vert_glsl__WEBPACK_IMPORTED_MODULE_3__["default"]].join('\n'), { replaceFirst: true }), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vertexReplacement)(POSITION_VC_IMPL_TOKEN, [POSITION_VC_IMPL_TOKEN, _shaders_annotation_fade_impl_vert_glsl__WEBPACK_IMPORTED_MODULE_5__["default"]].join('\n'), { replaceFirst: true }), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.fragmentReplacement)(POSITION_VC_DEC_TOKEN, [POSITION_VC_DEC_TOKEN, _shaders_annotation_fade_decl_frag_glsl__WEBPACK_IMPORTED_MODULE_2__["default"]].join('\n'), { replaceFirst: true }), // Pre-replace on //VTK::Light::Impl, the token vtk.js expands into the // gl_FragData[0] = ... write. By inserting the token back at the start // of our replacement, vtk.js still substitutes its color-write code // first; our heatmap override then runs after and overwrites the color. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.fragmentReplacement)(LIGHT_IMPL_TOKEN, [LIGHT_IMPL_TOKEN, _shaders_annotation_fade_impl_frag_glsl__WEBPACK_IMPORTED_MODULE_4__["default"]].join('\n'), { replaceFirst: true }), // POST dedup (replaceFirst: false runs after replaceShaderValues). // When lastLightComplexity > 0, vtk.js also emits `uniform mat4 MCVCMatrix;` // via //VTK::Camera::Dec, producing a duplicate alongside our own // declaration above. This removes it. Not testable against the shipped // shader source — this anchor only exists post-substitution. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.vertexReplacement)('uniform mat4 MCVCMatrix;\nuniform mat4 MCVCMatrix;', 'uniform mat4 MCVCMatrix;', { replaceAll: true })]; /** * Convenience wrapper that resolves `FadeShaderParameters` from a viewport's * fade camera and the updater's selection state, then forwards to * `applyFadeShader`. No-op on non-ORTHOGRAPHIC viewports — the shader install * only makes sense on MPR (see comment on `applyFadeShader` above). */ function applyAnnotationFade(viewport, mapper, camera, selected) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportType.ORTHOGRAPHIC) return; if (!camera) { applyFadeShader(mapper, { cameraToPlaneDistance: 0, enabled: false, selected, visibleDistance: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.ANNOTATION_VISIBLE_DISTANCE_MM }); return; } const [px, py, pz] = camera.position; const [fx, fy, fz] = camera.focalPoint; applyFadeShader(mapper, { cameraToPlaneDistance: Math.hypot(fx - px, fy - py, fz - pz), enabled: true, selected, visibleDistance: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.ANNOTATION_VISIBLE_DISTANCE_MM }); } function applyFadeShader(mapper, parameters) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.setShaderReplacement)(mapper, ANNOTATION_FADE_FEATURE, REPLACEMENTS); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.setShaderCallback)(mapper, ANNOTATION_FADE_FEATURE, { callback: (_userData, cellBO) => { const current = parametersByMapper.get(mapper); if (!current) return; const program = cellBO.getProgram(); if (program.isUniformUsed('uFadeEnabled')) { program.setUniformi('uFadeEnabled', current.enabled ? 1 : 0); } if (program.isUniformUsed('uFadeVisibleDistance')) { program.setUniformf('uFadeVisibleDistance', current.visibleDistance); } if (program.isUniformUsed('uFadeSelectedAlpha')) { program.setUniformf('uFadeSelectedAlpha', _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA); } if (program.isUniformUsed('uFadeCameraToPlaneDistance')) { program.setUniformf('uFadeCameraToPlaneDistance', current.cameraToPlaneDistance); } if (program.isUniformUsed('uFadeSelected')) { program.setUniformi('uFadeSelected', current.selected ? 1 : 0); } }, userData: undefined }); parametersByMapper.set(mapper, parameters); } /***/ }, /***/ 59985 /*!***************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/angle-updater.ts ***! \***************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AngleUpdater: () => (/* binding */ AngleUpdater) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Filters/General/TubeFilter */ 21362); /* harmony import */ var _kitware_vtk_js_Filters_Sources_ArcSource__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Filters/Sources/ArcSource */ 80371); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./get-point-scale-for-viewport */ 51847); /* harmony import */ var _multi_point_updater__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./multi-point-updater */ 67792); class AngleUpdater extends _multi_point_updater__WEBPACK_IMPORTED_MODULE_6__.MultiPointUpdater { additionalActorList(additional) { if (!additional) return {}; const out = {}; if (additional.arc) out['arc'] = additional.arc.actor; return out; } additionalGhostList(additional) { if (!additional?.arc?.ghostActor) return {}; return { 'arc:ghost': additional.arc.ghostActor }; } refreshFadeForViewport(viewport, collection) { super.refreshFadeForViewport(viewport, collection); const arc = collection.additional?.arc; if (arc) { this.applyFadeToPolyLine(viewport, arc.mapper); } } updateAdditional(viewport, collection) { if (!collection.additional) { collection.additional = {}; } const { additional } = collection; this.syncArc(viewport, additional); } // If we don't interpolate the lines, the tubeFilter starts // looking wonky on some tighter angles. // If there are any performance issues, we can probably use a // lighter interpolation method as we don't have to handle any curves. getPolyLinePoints() { const [a, b, c] = this.current.points; const points = []; if (a && b) { points.push(...(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.calculateSplinePath)([a, b], false)); } if (b && c) { points.push(...(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.calculateSplinePath)([b, c], false).splice(1)); } return points; } syncArc(viewport, additional) { const [a, b, c] = this.current.points; if (a && b && c) { if (additional.arc) { this.updateArc(viewport, additional.arc, a, b, c); } else { additional.arc = this.createArc(viewport, [a, b, c]); } } else { if (additional.arc) { this.detachLineGhost(viewport, additional.arc, `${this.current.id}:arc:ghost`); this.deleteActor(viewport, additional.arc.actor, `${this.current.id}:arc`); additional.arc = undefined; } } } updateArc(viewport, arcDetails, a, b, c) { const { filter, mapper, source } = arcDetails; const { center, point1, point2 } = this.calculateArc(a, b, c); filter.setRadius((0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_5__.getPointScaleForViewport)(viewport, this.annotationSize)); source.setPoint1([...point1]); source.setPoint2([...point2]); source.setCenter([...center]); this.applyFadeToPolyLine(viewport, mapper); } createArc(viewport, controlPoints) { const [a, b, c] = controlPoints; const { center, point1, point2 } = this.calculateArc(a, b, c); const source = _kitware_vtk_js_Filters_Sources_ArcSource__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ center: [...center], point1: [...point1], point2: [...point2], resolution: 32 }); const filter = _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ capping: true, numberOfSides: 32, radius: (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_5__.getPointScaleForViewport)(viewport, this.annotationSize), sidesShareVertices: false }); filter.setInputConnection(source.getOutputPort()); const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(filter); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationActor)(viewport, `${this.current.id}:arc`, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); // Set custom property for easy lookup on actor clicks, etc actor.set({ annotationId: this.current.id }, true); filter.update(); mapper.getBounds(); this.applyFadeToPolyLine(viewport, mapper); const arc = { actor, filter, mapper, source }; this.attachLineGhost(viewport, arc, `${this.current.id}:arc:ghost`); return arc; } calculateArc(a, b, c) { const length1 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.distance(a, b); const length2 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.distance(c, b); const point1 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); const point2 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); if (length2 > length1) { gl_matrix__WEBPACK_IMPORTED_MODULE_3__.lerp(point1, b, a, 0.3); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.lerp(point2, b, c, 0.3); } else { gl_matrix__WEBPACK_IMPORTED_MODULE_3__.lerp(point1, b, c, 0.3); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.lerp(point2, b, a, 0.3); } return { center: b, point1: point1, point2: point2 }; } } /***/ }, /***/ 55127 /*!***********************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/constants.ts ***! \***********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CREATED_POINT_SCALE: () => (/* binding */ CREATED_POINT_SCALE), /* harmony export */ DEFAULT_ANNOTATION_RADIUS: () => (/* binding */ DEFAULT_ANNOTATION_RADIUS), /* harmony export */ GHOST_OPACITY: () => (/* binding */ GHOST_OPACITY), /* harmony export */ HOVERED_POINT_SCALE: () => (/* binding */ HOVERED_POINT_SCALE) /* harmony export */ }); const CREATED_POINT_SCALE = 1.5; const HOVERED_POINT_SCALE = 1.5; const DEFAULT_ANNOTATION_RADIUS = 2; const GHOST_OPACITY = 0.4; /***/ }, /***/ 44967 /*!******************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/distance-updater.ts ***! \******************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DistanceUpdater: () => (/* binding */ DistanceUpdater) /* harmony export */ }); /* harmony import */ var _multi_point_updater__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./multi-point-updater */ 67792); class DistanceUpdater extends _multi_point_updater__WEBPACK_IMPORTED_MODULE_0__.MultiPointUpdater {} /***/ }, /***/ 51847 /*!******************************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/get-point-scale-for-viewport.ts ***! \******************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getPointScaleForViewport: () => (/* binding */ getPointScaleForViewport) /* harmony export */ }); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ 55127); const getPointScaleForViewport = (viewport, radiusPx = _constants__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_ANNOTATION_RADIUS) => { if (!viewport) { return 1; } const renderer = viewport.getRenderer(); const camera = renderer.getActiveCamera(); const canvasHeight = viewport.canvas?.clientHeight ?? 1; return radiusPx * (2 * camera.getParallelScale() / canvasHeight) * globalThis.devicePixelRatio; }; /***/ }, /***/ 67792 /*!*********************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/multi-point-updater.ts ***! \*********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MultiPointUpdater: () => (/* binding */ MultiPointUpdater) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Filters/General/TubeFilter */ 21362); /* harmony import */ var _kitware_vtk_js_Filters_Sources_SphereSource__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Filters/Sources/SphereSource */ 52284); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _vtk_poly_line_source__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../vtk-poly-line-source */ 48333); /* harmony import */ var _annotation_fade_shader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../annotation-fade-shader */ 75939); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./constants */ 55127); /* harmony import */ var _get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./get-point-scale-for-viewport */ 51847); // We can share the same source for all control points, because // only actor-specific properties change. // The actual line between points will have to be annotation-specific. const POINT_SOURCE = _kitware_vtk_js_Filters_Sources_SphereSource__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ phiResolution: 25, radius: 2, thetaResolution: 25 }); class MultiPointUpdater { current; viewports; interactionState; _annotationSize; static pointSource = POINT_SOURCE; actorLookup = new Map(); fadeCameras = {}; projectionMode = false; mouseWorldPosition = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.position)(0, 0, 0); hidesPrimary(viewport) { return this.projectionMode && viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportType.VOLUME_3D; } ghostOpacity() { return this.projectionMode ? 1 : _constants__WEBPACK_IMPORTED_MODULE_7__.GHOST_OPACITY; } get isSelected() { return [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.AnnotationInteractionState.ADDING_POINTS, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.AnnotationInteractionState.BEING_CREATED, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.AnnotationInteractionState.SELECTED].includes(this.interactionState); } // Override where necessary showPoint(index) { return true; } // Override where necessary pointIsPickable(index) { return true; } get isBeingCreated() { return this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.AnnotationInteractionState.BEING_CREATED; } get isAddingPoints() { return this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.AnnotationInteractionState.ADDING_POINTS; } _isHovered = false; get isHovered() { return this._isHovered; } _hoveredPointIndex; get hoveredPointIndex() { return this._hoveredPointIndex; } get annotationSize() { return this._annotationSize; } constructor(current, viewports, interactionState, _annotationSize) { this.current = current; this.viewports = viewports; this.interactionState = interactionState; this._annotationSize = _annotationSize; this.updateActors(); } setMouseWorldPosition(mouseWorldPosition) { if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.positionsEqual)(this.mouseWorldPosition, mouseWorldPosition)) { this.mouseWorldPosition = mouseWorldPosition; this.updateActors(); } } get annotation() { return this.current; } update(annotation) { if (annotation !== this.current && annotation.type === this.current.type) { this.current = annotation; this.updateActors(); } } setAnnotationSize(annotationSize) { if (annotationSize !== this._annotationSize) { this._annotationSize = annotationSize; this.updateActors(); } } setInteractionState(interactionState) { if (interactionState !== this.interactionState) { this.interactionState = interactionState; this.updateActors(); } } setProjectionMode(projectionMode) { if (projectionMode !== this.projectionMode) { this.projectionMode = projectionMode; this.updateActors(); } } setIsHovered(isHovered, pointIndex) { if (isHovered !== this._isHovered || pointIndex !== this._hoveredPointIndex) { this._isHovered = isHovered; this._hoveredPointIndex = isHovered ? pointIndex : undefined; this.updateActors(); } } setViewports(viewports) { // Remove actors for any unregistered viewport const removals = this.viewports.filter(vp => !viewports.includes(vp)); for (const viewport of removals) { this.removeActorsForViewport(viewport); } // Otherwise, add or update any viewports as necessary this.viewports = viewports; this.updateActors(); } cleanup() { // Destroy all actors and remove from viewports for (const viewport of this.viewports) { this.removeActorsForViewport(viewport); } } refreshFade(camerasByViewportId) { this.fadeCameras = camerasByViewportId; for (const viewport of this.viewports) { const collection = this.actorLookup.get(viewport.id); if (!collection) continue; this.refreshFadeForViewport(viewport, collection); } } refreshFadeForViewport(viewport, collection) { this.applyFadeToPolyLine(viewport, collection.polyLine.mapper); for (const [index, actor] of collection.controlPoints.entries()) { const point = this.current.points[index]; if (!point) continue; actor.setVisibility(this.isPointInBand(viewport, point) && this.showPoint(index) && !this.hidesPrimary(viewport)); } } /** * Hard on/off for point-shaped actors (control points, single points, * preview point). Points are discarded out-of-band rather than faded. */ isPointInBand(viewport, worldPoint) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportType.ORTHOGRAPHIC) return true; const camera = this.fadeCameras[viewport.id]; if (!camera) return true; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationPointInBand)(worldPoint, camera.focalPoint, camera.viewPlaneNormal); } applyFadeToPolyLine(viewport, mapper) { (0,_annotation_fade_shader__WEBPACK_IMPORTED_MODULE_6__.applyAnnotationFade)(viewport, mapper, this.fadeCameras[viewport.id], this.isSelected); } updateActors() { // Update the state of each actor as necessary for (const viewport of this.viewports) { const collection = this.actorCollectionForViewport(viewport); this.updateActorCollection(viewport, collection); } } actorCollectionForViewport(viewport) { const existing = this.actorLookup.get(viewport.id); if (existing) { return existing; } const collection = { controlPoints: [], polyLine: this.initPolyLine(viewport) }; if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportType.VOLUME_3D) { collection.ghostPolyLine = this.initGhostPolyLine(viewport, collection.polyLine); collection.controlPointGhosts = []; } for (const [index, point] of this.current.points.entries()) { collection.controlPoints.push(this.createControlPoint(viewport, index, point)); if (collection.controlPointGhosts) { collection.controlPointGhosts.push(this.createControlPointGhost(viewport, index, point)); } } this.actorLookup.set(viewport.id, collection); return collection; } attachLineGhost(viewport, line, ghostUid) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.ViewportType.VOLUME_3D) return; const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(line.filter); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); actor.getProperty().setOpacity(this.ghostOpacity()); actor.set({ annotationId: this.current.id }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationGhostActor)(viewport, ghostUid, actor); line.ghostActor = actor; line.ghostMapper = mapper; } additionalGhostList(_additional) { return {}; } detachLineGhost(viewport, line, ghostUid) { if (!line.ghostActor) return; (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.removeAnnotationGhostActor)(viewport, ghostUid); line.ghostActor.delete(); line.ghostMapper?.delete(); line.ghostActor = undefined; line.ghostMapper = undefined; } initGhostPolyLine(viewport, primary) { const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(primary.filter); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); actor.getProperty().setOpacity(this.ghostOpacity()); actor.setVisibility(this.projectionMode || this.isSelected); actor.set({ annotationId: this.current.id }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationGhostActor)(viewport, `${this.current.id}:polyLine:ghost`, actor); return actor; } initPolyLine(viewport) { const source = _vtk_poly_line_source__WEBPACK_IMPORTED_MODULE_5__["default"].newInstance({ points: this.getPolyLinePoints() }); const filter = _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ capping: true, numberOfSides: 32, radius: (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this._annotationSize) }); filter.setInputConnection(source.getOutputPort()); const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(filter); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationActor)(viewport, `${this.current.id}:polyLine`, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); // Set custom property for easy lookup on actor clicks, etc actor.set({ annotationId: this.current.id }, true); filter.update(); mapper.getBounds(); this.applyFadeToPolyLine(viewport, mapper); return { actor, filter, mapper, source }; } updatePolyLine(details, viewport) { details.source.setPoints(this.getPolyLinePoints()); details.filter.setRadius((0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this._annotationSize)); this.applyFadeToPolyLine(viewport, details.mapper); } getPolyLinePoints() { return this.current.points; } createControlPoint(viewport, index, position) { const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(POINT_SOURCE); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.setPosition(...position); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationActor)(viewport, `${this.current.id}:${index}`, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); // Set custom property for easy lookup on actor clicks, etc actor.set({ annotationId: this.current.id, pointIndex: index }, true); const scale = this.getScaleForPoint(viewport, index); actor.setScale(scale, scale, scale); actor.setVisibility(this.isPointInBand(viewport, position) && !this.hidesPrimary(viewport) && this.showPoint(index)); actor.setPickable(this.pointIsPickable(index)); return actor; } createControlPointGhost(viewport, index, position) { const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.annotationMapper)(POINT_SOURCE); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.setPosition(...position); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.applyAnnotationLighting)(actor, viewport); actor.getProperty().setOpacity(this.ghostOpacity()); actor.set({ annotationId: this.current.id, pointIndex: index }, true); const scale = this.getScaleForPoint(viewport, index); actor.setScale(scale, scale, scale); actor.setPickable(this.pointIsPickable(index)); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.addAnnotationGhostActor)(viewport, `${this.current.id}:${index}:ghost`, actor); return actor; } deleteControlPointGhost(viewport, ghost) { const { annotationId, pointIndex } = ghost.get('annotationId', 'pointIndex'); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.removeAnnotationGhostActor)(viewport, `${annotationId}:${pointIndex}:ghost`); const mapper = ghost.getMapper(); ghost.delete(); mapper?.delete(); } removeActorsForViewport(viewport) { const actorCollection = this.actorLookup.get(viewport.id); if (!actorCollection) return; this.actorLookup.delete(viewport.id); if (viewport.isDisabled) return; for (const actor of actorCollection.controlPoints) { this.deleteActor(viewport, actor); } if (actorCollection.controlPointGhosts) { for (const ghost of actorCollection.controlPointGhosts) { this.deleteControlPointGhost(viewport, ghost); } } if (actorCollection.additional) { const additionalActors = this.additionalActorList(actorCollection.additional); for (const [id, actor] of Object.entries(additionalActors)) { this.deleteActor(viewport, actor, `${this.current.id}:${id}`); } const additionalGhosts = this.additionalGhostList(actorCollection.additional); for (const [id, ghost] of Object.entries(additionalGhosts)) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.removeAnnotationGhostActor)(viewport, `${this.current.id}:${id}`); const mapper = ghost.getMapper(); ghost.delete(); mapper?.delete(); } } if (actorCollection.ghostPolyLine) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.removeAnnotationGhostActor)(viewport, `${this.current.id}:polyLine:ghost`); const ghostMapper = actorCollection.ghostPolyLine.getMapper(); actorCollection.ghostPolyLine.delete(); ghostMapper?.delete(); } this.deleteActor(viewport, actorCollection.polyLine.actor, `${this.current.id}:polyLine`); actorCollection.polyLine.filter.delete(); actorCollection.polyLine.mapper.delete(); actorCollection.polyLine.source.delete(); } updateActorCollection(viewport, collection) { if (this.isSelected) { this.updateActorCollectionSelected(viewport, collection); } else { this.updateActorCollectionDeselected(viewport, collection); } collection.polyLine.actor.setVisibility(!this.hidesPrimary(viewport)); const toUpdate = [...collection.controlPoints, collection.polyLine.actor, ...this.syncOverlayGhosts(collection)]; const { b, g, r } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.parseHexColor)(this.current.color) ?? { b: 0, g: 0, r: 0 }; for (const actor of toUpdate) { actor.getProperty().setColor(r / 255, g / 255, b / 255); } } /** Syncs overlay ghost opacity/visibility, then returns every actor still needing a colour refresh. */ syncOverlayGhosts(collection) { const toUpdate = []; const ghostVisible = this.projectionMode || this.isSelected; if (collection.additional) { const additionalPrimaries = this.additionalActorList(collection.additional); const additionalGhosts = this.additionalGhostList(collection.additional); for (const [key, actor] of Object.entries(additionalPrimaries)) { // Skip preview-only primaries (no ghost twin) so they stay visible during creation. if (`${key}:ghost` in additionalGhosts) actor.setVisibility(!this.projectionMode); toUpdate.push(actor); } for (const ghost of Object.values(additionalGhosts)) { ghost.getProperty().setOpacity(this.ghostOpacity()); ghost.setVisibility(ghostVisible); toUpdate.push(ghost); } } if (collection.ghostPolyLine) { collection.ghostPolyLine.getProperty().setOpacity(this.ghostOpacity()); collection.ghostPolyLine.setVisibility(ghostVisible); toUpdate.push(collection.ghostPolyLine); } if (collection.controlPointGhosts) { for (const ghost of collection.controlPointGhosts) { ghost.getProperty().setOpacity(this.ghostOpacity()); } toUpdate.push(...collection.controlPointGhosts); } return toUpdate; } updateActorCollectionSelected(viewport, collection) { const points = this.current.points; for (const [index, point] of points.entries()) { this.updatePoint(collection, index, viewport, point); } while (collection.controlPoints.length > points.length) { const removed = collection.controlPoints.pop(); if (removed) this.deleteActor(viewport, removed); const removedGhost = collection.controlPointGhosts?.pop(); if (removedGhost) this.deleteControlPointGhost(viewport, removedGhost); } this.updatePolyLine(collection.polyLine, viewport); this.updateAdditional(viewport, collection); } updateActorCollectionDeselected(viewport, collection) { // No control points when annotation isn't selected this.removeControlPoints(viewport, collection); this.updatePolyLine(collection.polyLine, viewport); this.updateAdditional(viewport, collection); } updatePoint(collection, index, viewport, position) { const actor = collection.controlPoints[index]; const scale = this.getScaleForPoint(viewport, index); const visible = this.isPointInBand(viewport, position) && this.showPoint(index); if (actor) { actor.setPosition(...position); actor.setScale(scale, scale, scale); actor.setVisibility(visible && !this.hidesPrimary(viewport)); actor.setPickable(this.pointIsPickable(index)); } else { collection.controlPoints[index] = this.createControlPoint(viewport, index, position); } if (!collection.controlPointGhosts) return; const ghost = collection.controlPointGhosts[index]; if (ghost) { ghost.setPosition(...position); ghost.setScale(scale, scale, scale); ghost.setVisibility(visible); ghost.setPickable(this.pointIsPickable(index)); } else { collection.controlPointGhosts[index] = this.createControlPointGhost(viewport, index, position); } } removeControlPoints(viewport, collection) { for (const actor of collection.controlPoints) { this.deleteActor(viewport, actor); } collection.controlPoints = []; if (collection.controlPointGhosts) { for (const ghost of collection.controlPointGhosts) { this.deleteControlPointGhost(viewport, ghost); } collection.controlPointGhosts = []; } } deleteActor(viewport, actor, id) { const { annotationId, pointIndex } = actor.get('annotationId', 'pointIndex'); const uid = id ?? (pointIndex === undefined ? annotationId : `${annotationId}:${pointIndex}`); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.removeAnnotationActor)(viewport, uid); actor.delete(); } updateAdditional(viewport, collection) { // Override where needed } additionalActorList(additional) { // Override where needed return {}; } getScaleForPoint(viewport, index) { const baseScale = (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this._annotationSize); return this.hoveredPointIndex === index ? baseScale * _constants__WEBPACK_IMPORTED_MODULE_7__.HOVERED_POINT_SCALE : baseScale; } } /***/ }, /***/ 24309 /*!**********************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/object3d-shell-debug.ts ***! \**********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3DShellDebug: () => (/* binding */ Object3DShellDebug) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/PolyData */ 95765); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Mapper */ 55857); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); // Debug-only! Renders the convex-hull picking shell as a translucent wireframe // next to the visible mesh. Lets us see the picking proxy directly in the // viewport. // Toggle via: // localStorage.setItem('__TVCT_DEBUG__', JSON.stringify({ showShell: true })); // location.reload(); const SHELL_DEBUG_RGB = [1, 0.5, 0]; const SHELL_DEBUG_OPACITY = 0.25; const SHELL_REPRESENTATION_WIREFRAME = 1; /** Per-annotation debug overlay; one wireframe actor per viewport. */ class Object3DShellDebug { annotationId; registryKey; shell; polyData; actors = new Map(); constructor(annotationId, registryKey, shell) { this.annotationId = annotationId; this.registryKey = registryKey; this.shell = shell; } syncTo(viewports, userMatrix) { for (const viewport of viewports) { this.actorFor(viewport)?.setUserMatrix(userMatrix); } } removeFor(viewport) { const actor = this.actors.get(viewport.id); if (!actor) return; this.actors.delete(viewport.id); if (!viewport.isDisabled) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.removeAnnotationActor)(viewport, this.registryKey); actor.delete(); } cleanup(viewports) { for (const viewport of viewports) this.removeFor(viewport); } actorFor(viewport) { const existing = this.actors.get(viewport.id); if (existing) return existing; if (viewport.isDisabled) return undefined; const mapper = _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance(); mapper.setInputData(this.getPolyData()); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ mapper }); actor.setUseBounds(false); // Hardware selector must ignore the wireframe; otherwise the cap-fan // edges intercept clicks meant for the bore. actor.setPickable(false); const property = actor.getProperty(); property.setColor(...SHELL_DEBUG_RGB); property.setOpacity(SHELL_DEBUG_OPACITY); property.setRepresentation(SHELL_REPRESENTATION_WIREFRAME); property.setBackfaceCulling(false); actor.set({ annotationId: this.annotationId, isDebugShell: true }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.addAnnotationActor)(viewport, this.registryKey, actor); this.actors.set(viewport.id, actor); return actor; } getPolyData() { if (this.polyData) return this.polyData; const polyData = _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); polyData.getPoints().setData(this.shell.vertices, 3); // VTK cell format: [count, i0, i1, i2, ...] per triangle. const triangleCount = this.shell.indices.length / 3; const cells = new Uint32Array(triangleCount * 4); for (let triangle = 0; triangle < triangleCount; triangle++) { const cellOffset = triangle * 4; const indexOffset = triangle * 3; cells[cellOffset] = 3; cells[cellOffset + 1] = this.shell.indices[indexOffset] ?? 0; cells[cellOffset + 2] = this.shell.indices[indexOffset + 1] ?? 0; cells[cellOffset + 3] = this.shell.indices[indexOffset + 2] ?? 0; } polyData.getPolys().setData(cells); this.polyData = polyData; return polyData; } } /***/ }, /***/ 50980 /*!******************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/object3d-updater.ts ***! \******************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3DUpdater: () => (/* binding */ Object3DUpdater) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/Core/DataArray */ 40928); /* harmony import */ var _kitware_vtk_js_Common_DataModel_Plane__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/Plane */ 68497); /* harmony import */ var _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/PolyData */ 95765); /* harmony import */ var _kitware_vtk_js_Filters_Core_Cutter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @kitware/vtk.js/Filters/Core/Cutter */ 24712); /* harmony import */ var _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @kitware/vtk.js/Filters/General/TubeFilter */ 21362); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Mapper */ 55857); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./constants */ 55127); /* harmony import */ var _get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./get-point-scale-for-viewport */ 51847); /* harmony import */ var _object3d_shell_debug__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./object3d-shell-debug */ 24309); // Cutter outline tube radius, as a fraction of the global annotation size. // Derived the same way spline/measurement tubes get their thickness // (`getPointScaleForViewport`) so it stays a constant screen size across zoom. const CUTTER_RADIUS_FRACTION = 0.75; const CUTTER_TUBE_SIDES = 3; // Opacity of the surface mesh on MPR while selected. Lower than the VR ghost // (`GHOST_OPACITY`) so the cutter cross-section reads clearly through it. const MPR_SELECTED_MESH_OPACITY = 0.25; // Re-cutting a mesh on every camera tick is an O(triangles) scan. Above this // cell count (typically full anatomical segmentation STLs) it stalls // interaction, so the MPR cuts are hidden instead. Lifting the cap needs a // faster cut path. // // TODO The issue should be resolved in a separate spike: https://tomoverse.atlassian.net/browse/TVC-868 const MAX_LIVE_CUT_CELLS = 100_000; /** * Renders Object3D annotations (Cylinder, Hollow Cylinder, STL) in VTK viewports. * * Geometry is read from `Object3DGeometryStore` by annotation id, so callers * must seed the store before `addAnnotation`. This keeps all subtypes on one * pipeline and keeps the DTO small (no mesh payloads on recolor/rename/rotate). * * Actors use `setUseBounds(false)` so they don't participate in scene bounds; * otherwise `resetCamera` would shift the focal point and misalign the volume * mapper's proximal/distal clipping planes. * * Rendering per viewport: * - MPR (orthographic): the slice-plane cross-section as a tube outline, * always visible; plus the full surface mesh at reduced opacity, shown only * while selected. The surface mesh does not use the in-plane fade shader. * - VR (3D): the full opaque surface mesh, plus a translucent ghost shown only * while selected. */ class Object3DUpdater { current; viewports; interactionState; geometry; annotationSize; actorLookup = new Map(); ghostLookup = new Map(); cutterLookup = new Map(); fadeCameras = {}; projectionMode = false; polyData; meshBounds; shellDebug; constructor(current, viewports, interactionState, geometry, annotationSize) { this.current = current; this.viewports = viewports; this.interactionState = interactionState; this.geometry = geometry; this.annotationSize = annotationSize; if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.getDebugFlagByName)('showShell') && this.geometry.shell) { this.shellDebug = new _object3d_shell_debug__WEBPACK_IMPORTED_MODULE_14__.Object3DShellDebug(this.current.id, `${this.actorKey}:shell`, this.geometry.shell); } this.updateActors(); } get isSelected() { return this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationInteractionState.BEING_CREATED || this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.AnnotationInteractionState.SELECTED; } get annotation() { return this.current; } update(annotation) { if (annotation !== this.current && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.annotationIsObject3D)(annotation)) { this.current = annotation; this.updateActors(); } } setAnnotationSize(annotationSize) { if (annotationSize === this.annotationSize) return; this.annotationSize = annotationSize; const userMatrix = this.userMatrix; for (const viewport of this.viewports) { const cutter = this.cutterLookup.get(viewport.id); if (cutter) this.updateCutter(viewport, cutter, userMatrix); } } refreshFade(camerasByViewportId) { this.fadeCameras = camerasByViewportId; const userMatrix = this.userMatrix; for (const viewport of this.viewports) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportType.ORTHOGRAPHIC) continue; const cutter = this.cutterLookup.get(viewport.id); if (cutter) this.updateCutter(viewport, cutter, userMatrix); } } setInteractionState(interactionState) { if (interactionState === this.interactionState) return; this.interactionState = interactionState; // The full surface mesh is only shown while selected — translucent on MPR // (the primary actor) and as the ghost on VR. The cutter outline is always // visible and unaffected. The screen-space selection outline is a separate // post-process pass keyed off the actor's `outlinable` flag, not this state. for (const viewport of this.viewports) { if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportType.ORTHOGRAPHIC) { this.actorLookup.get(viewport.id)?.setVisibility(this.isSelected); } this.ghostLookup.get(viewport.id)?.setVisibility(this.projectionMode || this.isSelected); } } setMouseWorldPosition(_mouseWorldPosition) { // Object3D annotations don't react to mouse position. } setProjectionMode(projectionMode) { if (projectionMode === this.projectionMode) return; this.projectionMode = projectionMode; this.applyProjectionState(); } applyProjectionState() { for (const viewport of this.viewports) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportType.VOLUME_3D) continue; this.actorLookup.get(viewport.id)?.setVisibility(!this.projectionMode); const ghost = this.ghostLookup.get(viewport.id); if (ghost) { ghost.getProperty().setOpacity(this.projectionMode ? 1 : _constants__WEBPACK_IMPORTED_MODULE_12__.GHOST_OPACITY); ghost.setVisibility(this.projectionMode || this.isSelected); } } } setIsHovered(_isHovered, _pointIndex) { // No hover visual for Object3D annotations. } setViewports(viewports) { const removals = this.viewports.filter(vp => !viewports.includes(vp)); for (const viewport of removals) { this.removeActorForViewport(viewport); } this.viewports = viewports; this.updateActors(); } cleanup() { for (const viewport of this.viewports) { this.removeActorForViewport(viewport); } } get actorKey() { return `${this.current.id}:${this.current.type}`; } /** Mesh→world transform shared by the surface, ghost, and cutter actors. */ get userMatrix() { return (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_10__.getObject3DTransformMatrix)(this.current); } /** True when the mesh is too large to re-cut live. */ get hideCuts() { return this.getPolyData().getPolys().getNumberOfCells() > MAX_LIVE_CUT_CELLS; } updateActors() { const userMatrix = this.userMatrix; for (const viewport of this.viewports) { this.updateActor(this.actorForViewport(viewport), userMatrix); const ghost = this.ghostLookup.get(viewport.id); if (ghost) this.updateActor(ghost, userMatrix); const cutter = this.cutterLookup.get(viewport.id); if (cutter) { this.updateActor(cutter.actor, userMatrix); // Actor transform moved → mesh-space cut plane needs re-deriving from // the latest world-space slice plane. this.updateCutter(viewport, cutter, userMatrix); } } this.shellDebug?.syncTo(this.viewports, userMatrix); } /** vtkActor wrapping the full surface mesh, shared setup for the primary and ghost actors. */ createMeshActor(viewport) { const mapper = _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_6__["default"].newInstance(); mapper.setInputData(this.getPolyData()); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_5__["default"].newInstance({ mapper }); actor.setUseBounds(false); actor.setUserMatrix(this.userMatrix); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.applyAnnotationLighting)(actor, viewport); return actor; } /** Cached vtkActor for the viewport, created on first access. * Lives on the annotation overlay renderer so it joins the hardware-selector pass. */ actorForViewport(viewport) { const existing = this.actorLookup.get(viewport.id); if (existing) return existing; const actor = this.createMeshActor(viewport); // `outlinable: true` opts this actor into the screen-space outline pass. actor.set({ annotationId: this.current.id, outlinable: true }, true); if (!viewport.isDisabled) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.addAnnotationActor)(viewport, this.actorKey, actor); if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportType.VOLUME_3D) { // Wide clipping range so geometry past the volume isn't z-clipped. viewport.getRenderer().getActiveCamera().setClippingRange(-9999, 9999); actor.setVisibility(!this.projectionMode); this.ghostLookup.set(viewport.id, this.createGhost(viewport)); } if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_9__.ViewportType.ORTHOGRAPHIC) { // On MPR the surface mesh is a translucent presence shown only while // selected; the cutter outline carries the slice cross-section. actor.getProperty().setOpacity(MPR_SELECTED_MESH_OPACITY); actor.setVisibility(this.isSelected); this.cutterLookup.set(viewport.id, this.createCutterActor(viewport)); } } this.actorLookup.set(viewport.id, actor); return actor; } createGhost(viewport) { const actor = this.createMeshActor(viewport); actor.getProperty().setOpacity(this.projectionMode ? 1 : _constants__WEBPACK_IMPORTED_MODULE_12__.GHOST_OPACITY); actor.setVisibility(this.projectionMode || this.isSelected); actor.set({ annotationId: this.current.id }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.addAnnotationGhostActor)(viewport, `${this.actorKey}:ghost`, actor); return actor; } /** * Renders the slice-plane × mesh intersection as a tube outline on MPR. * Without this, a cylinder oriented along the view vector has no geometry * *in* the slice plane — its side walls are perpendicular to the camera, so * the surface mesh alone shows nothing there. The cutter gives a precise * cross-section that's always present at the slice regardless of orientation. * * The cut polylines are tubed (rather than drawn as GL lines) so thickness is * reliable across GPUs and scales with the annotation size, matching how the * spline/measurement annotations render their lines. */ createCutterActor(viewport) { const plane = _kitware_vtk_js_Common_DataModel_Plane__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(); const cutter = _kitware_vtk_js_Filters_Core_Cutter__WEBPACK_IMPORTED_MODULE_3__["default"].newInstance(); cutter.setInputData(this.getPolyData()); cutter.setCutFunction(plane); const tube = _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_4__["default"].newInstance({ capping: true, numberOfSides: CUTTER_TUBE_SIDES }); tube.setInputConnection(cutter.getOutputPort()); const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.annotationMapper)(tube); const userMatrix = this.userMatrix; const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_5__["default"].newInstance({ mapper }); actor.setUseBounds(false); actor.setUserMatrix(userMatrix); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.applyAnnotationLighting)(actor, viewport); // Hidden until we have a fade camera to derive the cut plane from. actor.setVisibility(false); actor.set({ annotationId: this.current.id }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.addAnnotationActor)(viewport, `${this.actorKey}:cutter`, actor); const record = { actor, cutter, mapper, plane, tube }; this.updateCutter(viewport, record, userMatrix); return record; } /** * Syncs the cutter to the viewport's current slice and zoom: the tube radius * (constant screen size) and the implicit cut plane. * * The cutter operates on the polyData in mesh-coord space, but the slice * plane is in world coords. Transforming the plane (origin + normal) into * mesh coords once is cheap; transforming every vertex of the mesh would * cost on every camera move. */ updateCutter(viewport, record, userMatrix) { if (this.hideCuts) { record.actor.setVisibility(false); return; } const camera = this.fadeCameras[viewport.id]; if (!camera) { record.actor.setVisibility(false); return; } const inv = gl_matrix__WEBPACK_IMPORTED_MODULE_7__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_7__.invert(inv, userMatrix); // Point (w=1): full affine, translation included. const [fx, fy, fz] = camera.focalPoint; const origin = [inv[0] * fx + inv[4] * fy + inv[8] * fz + inv[12], inv[1] * fx + inv[5] * fy + inv[9] * fz + inv[13], inv[2] * fx + inv[6] * fy + inv[10] * fz + inv[14]]; // Direction (w=0): rotation only. userMatrix is rigid (rotation + // translation, plus the STL axis-of-symmetry rotation), so the inverse // rotation applied to a normal preserves length within float precision. const [nx, ny, nz] = camera.viewPlaneNormal; const normal = [inv[0] * nx + inv[4] * ny + inv[8] * nz, inv[1] * nx + inv[5] * ny + inv[9] * nz, inv[2] * nx + inv[6] * ny + inv[10] * nz]; const magnitude = Math.hypot(...normal); if (magnitude > 0) { normal[0] /= magnitude; normal[1] /= magnitude; normal[2] /= magnitude; } // Broad-phase cull: if the mesh bounds sit entirely on one side of the // slice, the cross-section is empty. Hide the actor and leave the cut plane // untouched, so the cutter (an O(triangles) scan) doesn't re-execute for a // model that isn't on the current slice. if (!this.boundsStraddlePlane(origin, normal)) { record.actor.setVisibility(false); return; } record.actor.setVisibility(true); record.tube.setRadius((0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_13__.getPointScaleForViewport)(viewport, this.annotationSize * CUTTER_RADIUS_FRACTION)); record.plane.setOrigin(...origin); record.plane.setNormal(...normal); } /** Mesh-space axis-aligned bounds (center + half-extents), cached. */ getMeshBounds() { if (!this.meshBounds) { const [xMin, xMax, yMin, yMax, zMin, zMax] = this.getPolyData().getBounds(); this.meshBounds = { center: [(xMin + xMax) / 2, (yMin + yMax) / 2, (zMin + zMax) / 2], halfExtents: [(xMax - xMin) / 2, (yMax - yMin) / 2, (zMax - zMin) / 2] }; } return this.meshBounds; } /** * AABB-vs-plane test in mesh space: true when the bounding box crosses the * plane (so a cross-section exists). `normal` must be unit length. */ boundsStraddlePlane(origin, normal) { const { center, halfExtents } = this.getMeshBounds(); const centerDistance = normal[0] * (center[0] - origin[0]) + normal[1] * (center[1] - origin[1]) + normal[2] * (center[2] - origin[2]); const boxReach = halfExtents[0] * Math.abs(normal[0]) + halfExtents[1] * Math.abs(normal[1]) + halfExtents[2] * Math.abs(normal[2]); return Math.abs(centerDistance) <= boxReach; } getPolyData() { this.polyData ??= this.buildPolyData(); return this.polyData; } buildPolyData() { const polyData = _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance(); polyData.getPoints().setData(this.geometry.vertices, 3); const normals = _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ name: 'Normals', numberOfComponents: 3, values: this.geometry.normals }); polyData.getPointData().setNormals(normals); if (this.geometry.indices.length > 0) { polyData.getPolys().setData(this.geometry.indices); } else { // Triangle soup: every 3 vertices form one triangle. // VTK cell format: [count, i0, i1, i2, ...] const triangleCount = this.geometry.vertices.length / 9; const cells = new Uint32Array(triangleCount * 4); for (let triangle = 0; triangle < triangleCount; triangle++) { const cellOffset = triangle * 4; const vertexOffset = triangle * 3; cells[cellOffset] = 3; cells[cellOffset + 1] = vertexOffset; cells[cellOffset + 2] = vertexOffset + 1; cells[cellOffset + 3] = vertexOffset + 2; } polyData.getPolys().setData(cells); } return polyData; } removeActorForViewport(viewport) { const actor = this.actorLookup.get(viewport.id); const ghost = this.ghostLookup.get(viewport.id); const cutter = this.cutterLookup.get(viewport.id); this.actorLookup.delete(viewport.id); this.ghostLookup.delete(viewport.id); this.cutterLookup.delete(viewport.id); // Actor/ghost/cutter live on the annotation overlay renderer; only the // renderer removal is skipped when the viewport is gone, but the VTK // objects are always freed to avoid leaking them on disable. if (actor) { if (!viewport.isDisabled) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.removeAnnotationActor)(viewport, this.actorKey); actor.delete(); } if (ghost) { if (!viewport.isDisabled) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.removeAnnotationGhostActor)(viewport, `${this.actorKey}:ghost`); const ghostMapper = ghost.getMapper(); ghost.delete(); ghostMapper?.delete(); } if (cutter) { if (!viewport.isDisabled) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.removeAnnotationActor)(viewport, `${this.actorKey}:cutter`); cutter.actor.delete(); cutter.mapper.delete(); cutter.tube.delete(); cutter.cutter.delete(); cutter.plane.delete(); } this.shellDebug?.removeFor(viewport); } updateActor(actor, userMatrix) { const { b, g, r } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.parseHexColor)(this.current.color) ?? { b: 0, g: 0, r: 0 }; actor.getProperty().setColor(r / 255, g / 255, b / 255); actor.setUserMatrix(userMatrix); } } /***/ }, /***/ 4800 /*!***************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/point-updater.ts ***! \***************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PointUpdater: () => (/* binding */ PointUpdater), /* harmony export */ SOURCE: () => (/* binding */ SOURCE) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Filters_Sources_SphereSource__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Filters/Sources/SphereSource */ 52284); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./constants */ 55127); /* harmony import */ var _get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./get-point-scale-for-viewport */ 51847); function isPointInBand(viewport, camera, worldPoint) { if (viewport.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportType.ORTHOGRAPHIC) return true; if (!camera) return true; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.annotationPointInBand)(worldPoint, camera.focalPoint, camera.viewPlaneNormal); } // We can share the same source for all points, because // only actor-specific properties change. // Other annotation types will likely need their own source/mapper per Updater instance. const SOURCE = _kitware_vtk_js_Filters_Sources_SphereSource__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ phiResolution: 25, radius: _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_ANNOTATION_RADIUS, thetaResolution: 25 }); /** * Keeps a reference to a `Point` instance and any active viewports. * * When updates are received for the point's state or which viewports are active, * the `vtkActor` instance for each viewport is updated to match the * new point's state. */ class PointUpdater { current; viewports; interactionState; annotationSize; actorLookup = new Map(); ghostLookup = new Map(); fadeCameras = {}; projectionMode = false; hidesPrimary(viewport) { return this.projectionMode && viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportType.VOLUME_3D; } constructor(current, viewports, interactionState, annotationSize) { this.current = current; this.viewports = viewports; this.interactionState = interactionState; this.annotationSize = annotationSize; this.updateActors(); } isHovered = false; get isSelected() { return this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationInteractionState.BEING_CREATED || this.interactionState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationInteractionState.SELECTED; } get annotation() { return this.current; } update(annotation) { if (annotation !== this.current && annotation.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.POINT) { this.current = annotation; this.updateActors(); } } setAnnotationSize(annotationSize) { if (annotationSize !== this.annotationSize) { this.annotationSize = annotationSize; this.updateActors(); } } setInteractionState(interactionState) { if (interactionState !== this.interactionState) { this.interactionState = interactionState; this.updateActors(); } } setMouseWorldPosition(mouseWorldPosition) { // Individual points don't care about mouse position } setProjectionMode(projectionMode) { if (projectionMode !== this.projectionMode) { this.projectionMode = projectionMode; this.updateActors(); } } setViewports(viewports) { // Remove actors for any unregistered viewport const removals = this.viewports.filter(vp => !viewports.includes(vp)); for (const viewport of removals) { this.removeActorForViewport(viewport); } // Otherwise, add or update any viewports as necessary this.viewports = viewports; this.updateActors(); } setIsHovered(isHovered, pointIndex) { // Because this is a single-point, we don't care about pointIndex if (this.isHovered !== isHovered) { this.isHovered = isHovered; this.updateActors(); } } cleanup() { // Destroy all actors and remove from viewports for (const viewport of this.viewports) { this.removeActorForViewport(viewport); } } refreshFade(camerasByViewportId) { this.fadeCameras = camerasByViewportId; for (const [viewportId, actor] of this.actorLookup) { const viewport = this.viewports.find(vp => vp.id === viewportId); if (!viewport) continue; actor.setVisibility(isPointInBand(viewport, this.fadeCameras[viewport.id], this.current.position) && !this.hidesPrimary(viewport)); } } updateActors() { // Update the state of each actor as necessary for (const viewport of this.viewports) { const actor = this.actorForViewport(viewport); this.updateActor(actor, viewport); const visible = isPointInBand(viewport, this.fadeCameras[viewport.id], this.current.position); actor.setVisibility(visible && !this.hidesPrimary(viewport)); const ghost = this.ghostLookup.get(viewport.id); if (ghost) { this.updateActor(ghost, viewport); ghost.getProperty().setOpacity(this.projectionMode ? 1 : _constants__WEBPACK_IMPORTED_MODULE_4__.GHOST_OPACITY); ghost.setVisibility(visible && (this.projectionMode || this.isSelected)); } } } actorForViewport(viewport) { const existing = this.actorLookup.get(viewport.id); if (existing) { return existing; } const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.annotationMapper)(SOURCE); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ mapper }); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.addAnnotationActor)(viewport, this.current.id, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.applyAnnotationLighting)(actor, viewport); // `pointIndex: 0` matches the control-point convention so click // handlers can treat the Point sphere as its sole control point. actor.set({ annotationId: this.current.id, pointIndex: 0 }, true); this.actorLookup.set(viewport.id, actor); if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportType.VOLUME_3D) { this.ghostLookup.set(viewport.id, this.createGhost(viewport)); } return actor; } createGhost(viewport) { const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.annotationMapper)(SOURCE); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ mapper }); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.applyAnnotationLighting)(actor, viewport); actor.getProperty().setOpacity(_constants__WEBPACK_IMPORTED_MODULE_4__.GHOST_OPACITY); actor.set({ annotationId: this.current.id, pointIndex: 0 }, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.addAnnotationGhostActor)(viewport, `${this.current.id}:ghost`, actor); return actor; } removeActorForViewport(viewport) { const actor = this.actorLookup.get(viewport.id); if (!actor) return; this.actorLookup.delete(viewport.id); const ghost = this.ghostLookup.get(viewport.id); this.ghostLookup.delete(viewport.id); if (viewport.isDisabled) return; (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.removeAnnotationActor)(viewport, this.current.id); actor.delete(); if (ghost) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.removeAnnotationGhostActor)(viewport, `${this.current.id}:ghost`); const ghostMapper = ghost.getMapper(); ghost.delete(); ghostMapper?.delete(); } } updateActor(actor, viewport) { const { b, g, r } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.parseHexColor)(this.current.color) ?? { b: 0, g: 0, r: 0 }; actor.getProperty().setColor(r / 255, g / 255, b / 255); // Point annotations use the same enlarged scale whether hovered or // selected, so the two states don't stack and the point is always the // same size when either is active. const emphasisScale = this.isSelected || this.isHovered ? _constants__WEBPACK_IMPORTED_MODULE_4__.HOVERED_POINT_SCALE : 1; const scale = emphasisScale * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_5__.getPointScaleForViewport)(viewport, this.annotationSize); actor.setScale(scale, scale, scale); actor.setPosition(...this.current.position); } } /***/ }, /***/ 62781 /*!****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/annotation-updaters/spline-updater.ts ***! \****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SplineUpdater: () => (/* binding */ SplineUpdater) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Filters/General/TubeFilter */ 21362); /* harmony import */ var _kitware_vtk_js_Filters_Sources_LineSource__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Filters/Sources/LineSource */ 98671); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Actor */ 77251); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./constants */ 55127); /* harmony import */ var _get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./get-point-scale-for-viewport */ 51847); /* harmony import */ var _multi_point_updater__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./multi-point-updater */ 67792); const AXIS_MARKER_RADIUS = 0.8; class SplineUpdater extends _multi_point_updater__WEBPACK_IMPORTED_MODULE_9__.MultiPointUpdater { isClosed = false; get showPreview() { return this.isAddingPoints || this.isBeingCreated; } constructor(current, viewports, interactionState, annotationSize) { super(current, viewports, interactionState, annotationSize); this.isClosed = (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationIsClosedSpline)(current); } // Points are always shown (base class default) - only their interactivity changes // while being created, in pointIsPickable below. pointIsPickable(index) { if (index === 0 && this.isBeingCreated && this.isClosed) { return this.annotation.points.length > 2; } // Placed points are visible as they're created, but not yet draggable/clickable - // they only become interactive once the spline itself is finished. return !this.isBeingCreated; } refreshFadeForViewport(viewport, collection) { super.refreshFadeForViewport(viewport, collection); const axisMarker = collection.additional?.axisMarker; if (axisMarker) { this.applyFadeToPolyLine(viewport, axisMarker.mapper); } } additionalActorList(additional) { if (!additional) return {}; const out = {}; if (additional.axisMarker) out['axisMarker'] = additional.axisMarker.actor; if (additional.previewPoint) out['previewPoint'] = additional.previewPoint.actor; return out; } additionalGhostList(additional) { if (!additional?.axisMarker?.ghostActor) return {}; return { 'axisMarker:ghost': additional.axisMarker.ghostActor }; } updateAdditional(viewport, collection) { if (!collection.additional) { collection.additional = {}; } const { additional } = collection; if (this.showPreview && this.current.points.length > 0) { // Create / update the preview point this.syncPreviewPoint(viewport, additional); } else { // Clear preview this.clearPreviewPoint(viewport, additional); } if (this.isClosed) { if (this.isSelected && !this.isBeingCreated && this.current.points.length > 1) { this.syncAxisMarker(viewport, additional); } else { this.clearAxisMarker(viewport, additional); } const hoverScale = this.isClosed && this.hoveredPointIndex === 0 ? _constants__WEBPACK_IMPORTED_MODULE_7__.HOVERED_POINT_SCALE : 1; const scale = hoverScale * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this.annotationSize); collection.controlPoints[0]?.setScale(scale, scale, scale); } } getPolyLinePoints() { if (this.current.points.length === 0) { return []; } const endPoint = this.current.points.at(-1); if (this.isBeingCreated) { const points = [...this.current.points]; // Hovering the first point of a closed spline previews the completed loop // instead of a rubber-band segment out to the cursor - close over the existing // points rather than extending them with the mouse position. const closingPreview = this.isClosed && this.hoveredPointIndex === 0; if (!closingPreview && gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dist(this.mouseWorldPosition, endPoint) > 1) { points.push(this.mouseWorldPosition); } return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.calculateSplinePath)(points, closingPreview); } return (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplinePath)(this.current); } syncPreviewPoint(viewport, additional) { // Don't show preview point when hovering over existing point in add points mode, // or when hovering over first point when creating closed spline const hoveringWhileAdding = this.isAddingPoints && this.hoveredPointIndex !== undefined; const closingSpline = this.isClosed && this.hoveredPointIndex === 0; if (additional.previewPoint && (hoveringWhileAdding || closingSpline)) { this.clearPreviewPoint(viewport, additional); return; } if (!additional.previewPoint) { additional.previewPoint = this.initPreviewPoint(viewport); } // In add point mode, we snap preview points to the spline let position = this.mouseWorldPosition; if (this.isAddingPoints && this.hoveredPointIndex === undefined) { position = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.snapPositionToSpline)(position, this.getPolyLinePoints()); } additional.previewPoint.actor.setPosition(...position); // Must match initPreviewPoint's formula - this overwrites that initial scale on every // sync (every mouse move), so omitting the viewport factor here previously left the // preview point's on-screen size tracking raw zoom instead of staying pixel-constant. const scale = (this.isAddingPoints ? 1 : 0.6) * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this.annotationSize); additional.previewPoint.actor.setScale(scale, scale, scale); } initPreviewPoint(viewport) { const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.annotationMapper)(SplineUpdater.pointSource); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.setPickable(false); actor.setPosition(...this.mouseWorldPosition); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.addAnnotationActor)(viewport, `${this.current.id}:previewPoint`, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.applyAnnotationLighting)(actor, viewport); const scale = 0.6 * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this.annotationSize); actor.setScale(scale, scale, scale); return { actor, mapper }; } clearPreviewPoint(viewport, additional) { const { previewPoint } = additional; if (previewPoint) { // Delete all actors etc this.deleteActor(viewport, previewPoint.actor, `${this.current.id}:previewPoint`); previewPoint.mapper.delete(); additional.previewPoint = undefined; } } getAxisMarkerPoints() { const centroid = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineCentroid)(this.current); const bestFitNormal = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplineBestFitNormal)(this.current); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.calculatePointsOnAxis)(centroid, bestFitNormal, 20); } initAxisMarker(viewport) { const [start, end] = this.getAxisMarkerPoints(); const source = _kitware_vtk_js_Filters_Sources_LineSource__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance({ point1: [...start], point2: [...end] }); const filter = _kitware_vtk_js_Filters_General_TubeFilter__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ capping: true, numberOfSides: 32, radius: AXIS_MARKER_RADIUS * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport) }); filter.addInputConnection(source.getOutputPort()); const mapper = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.annotationMapper)(filter); const actor = _kitware_vtk_js_Rendering_Core_Actor__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance({ mapper }); actor.getProperty().setBackfaceCulling(true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.addAnnotationActor)(viewport, `${this.current.id}:axisMarker`, actor); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_6__.applyAnnotationLighting)(actor, viewport); this.applyFadeToPolyLine(viewport, mapper); const line = { actor, filter, mapper, source }; this.attachLineGhost(viewport, line, `${this.current.id}:axisMarker:ghost`); return line; } syncAxisMarker(viewport, additional) { if (additional.axisMarker) { const [start, end] = this.getAxisMarkerPoints(); const { filter, mapper, source } = additional.axisMarker; filter.setRadius(AXIS_MARKER_RADIUS * (0,_get_point_scale_for_viewport__WEBPACK_IMPORTED_MODULE_8__.getPointScaleForViewport)(viewport, this.annotationSize)); source.setPoint1From([...start]); source.setPoint2From([...end]); source.modified(); this.applyFadeToPolyLine(viewport, mapper); } else { additional.axisMarker = this.initAxisMarker(viewport); } } clearAxisMarker(viewport, additional) { const { axisMarker } = additional; if (axisMarker) { this.detachLineGhost(viewport, axisMarker, `${this.current.id}:axisMarker:ghost`); // Delete all actors etc this.deleteActor(viewport, axisMarker.actor, `${this.current.id}:axisMarker`); axisMarker.mapper.delete(); additional.axisMarker = undefined; } } } /***/ }, /***/ 76045 /*!************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/camera-animation.service.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CameraAnimationService: () => (/* binding */ CameraAnimationService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tweenjs_tween_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tweenjs/tween.js */ 31307); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** Duration of the camera transition, in milliseconds. */ const CAMERA_TRANSITION_MS = 500; /** * Drives the animated camera transition: it owns the tween, the * rAF loop and the slerp/lerp interpolation, and patches the viewport store each frame. */ class CameraAnimationService { viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore); tween; rafId; settle; /** * Animate the camera focal point to `position`, optionally facing `normal`. */ animateToPosition(position, normal, hooks) { this.cancel(); if (this.prefersReducedMotion()) { this.viewportStore.setCameraToPosition(position, normal); return; } const start = { intersection: this.viewportStore.intersection(), isocenter: this.viewportStore.isocenter(), matrix: gl_matrix__WEBPACK_IMPORTED_MODULE_2__.clone(this.viewportStore.matrix()) }; const target = this.viewportStore.cameraTargetForPosition(position, normal); // Already at the target: - skip the tween. if (gl_matrix__WEBPACK_IMPORTED_MODULE_3__.equals((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.positionToVec3)(start.intersection), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.positionToVec3)(target.intersection)) && gl_matrix__WEBPACK_IMPORTED_MODULE_3__.equals((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.positionToVec3)(start.isocenter), (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.positionToVec3)(target.isocenter)) && (!target.matrix || gl_matrix__WEBPACK_IMPORTED_MODULE_2__.equals(start.matrix, target.matrix))) { return; } hooks?.onStart?.(); this.settle = hooks?.onSettle; const progress = { t: 0 }; this.tween = new _tweenjs_tween_js__WEBPACK_IMPORTED_MODULE_1__.Tween(progress).to({ t: 1 }, CAMERA_TRANSITION_MS).easing(_tweenjs_tween_js__WEBPACK_IMPORTED_MODULE_1__.Easing.Cubic.InOut).onUpdate(() => this.viewportStore.setCameraState((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cameraStateAtProgress)(start, target, progress.t))).start(); const tick = () => { const tween = this.tween; if (!tween) return; tween.update(); if (tween.isPlaying()) { this.rafId = requestAnimationFrame(tick); return; } // Snap to the canonical target so the final state matches the instant path. this.viewportStore.setCameraToPosition(position, normal); this.cancel(); }; this.rafId = requestAnimationFrame(tick); } /** Cancel any in-flight animation and run the pending settle hook once. */ cancel() { if (this.rafId !== undefined) { cancelAnimationFrame(this.rafId); this.rafId = undefined; } this.tween?.stop(); this.tween = undefined; const settle = this.settle; this.settle = undefined; settle?.(); } prefersReducedMotion() { return globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false; } static ɵfac = function CameraAnimationService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CameraAnimationService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: CameraAnimationService, factory: CameraAnimationService.ɵfac }); } /***/ }, /***/ 36896 /*!*******************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/build-cpr-actor.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildCprActor: () => (/* binding */ buildCprActor), /* harmony export */ updateCprCenterline: () => (/* binding */ updateCprCenterline) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Rendering_Core_ImageCPRMapper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/ImageCPRMapper */ 96113); /* harmony import */ var _kitware_vtk_js_Rendering_Core_ImageSlice__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/ImageSlice */ 32745); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _spline_to_centerline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./spline-to-centerline */ 46815); function buildCprActor(imageData, spline, rollRad = 0) { const centerline = (0,_spline_to_centerline__WEBPACK_IMPORTED_MODULE_3__.splineToCenterline)(spline, rollRad); const mapper = _kitware_vtk_js_Rendering_Core_ImageCPRMapper__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); mapper.setInputData(imageData, 0); mapper.setInputData(centerline.polyData, 1); mapper.setWidth(_cpr_config__WEBPACK_IMPORTED_MODULE_2__.CPR_WIDTH_MM); mapper.setOrientationArrayName(_spline_to_centerline__WEBPACK_IMPORTED_MODULE_3__.CPR_ORIENTATION_ARRAY_NAME); mapper.useStraightenedMode(); const actor = _kitware_vtk_js_Rendering_Core_ImageSlice__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(); // vtkImageCPRMapper extends vtkAbstractMapper3D, not vtkAbstractImageMapper; // the runtime contract is compatible, the declared types don't match. actor.setMapper(mapper); return { actor, centerline, mapper }; } function updateCprCenterline(bundle, spline, rollRad = 0) { const centerline = (0,_spline_to_centerline__WEBPACK_IMPORTED_MODULE_3__.splineToCenterline)(spline, rollRad); bundle.mapper.setInputData(centerline.polyData, 1); bundle.centerline = centerline; return centerline; } /***/ }, /***/ 85367 /*!**********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/control-point-step.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ controlPointStepDelta: () => (/* binding */ controlPointStepDelta), /* harmony export */ normalizeCursorMm: () => (/* binding */ normalizeCursorMm) /* harmony export */ }); /** Pure arithmetic behind the ←/→ and a/d control-point stepping. */ /** Skips a control point the cursor is effectively already on. */ const STEP_EPSILON_MM = 0.5; /** * Undefined once an open spline is at its last control point. A closed spline's delta can * run past the seam — see `normalizeCursorMm`. */ function controlPointStepDelta(input) { const { closed, cursorMm, direction, distancesMm, totalLengthMm } = input; const sorted = distancesMm.toSorted((a, b) => a - b); // A closed cursor scrubbed to totalLength sits on the seam, which is 0: comparing from the // far end finds nothing ahead and wraps back onto the seam itself, so the key goes dead. const from = normalizeCursorMm(cursorMm, totalLengthMm, closed); const target = nextControlPointMm(sorted, from, direction, closed); if (target === undefined) return undefined; return sweepDelta(target - from, direction, closed ? totalLengthMm : undefined); } function nextControlPointMm(sorted, cursorMm, direction, closed) { const ahead = direction > 0 ? sorted.find(distance => distance > cursorMm + STEP_EPSILON_MM) : sorted.findLast(distance => distance < cursorMm - STEP_EPSILON_MM); if (ahead !== undefined) return ahead; if (!closed) return undefined; return direction > 0 ? sorted[0] : sorted.at(-1); } /** Force the sweep the way the key was pressed; an open arc has no way round to force. */ function sweepDelta(delta, direction, totalLengthMm) { if (totalLengthMm === undefined) return delta; if (direction > 0 && delta <= 0) return delta + totalLengthMm; if (direction < 0 && delta >= 0) return delta - totalLengthMm; return delta; } /** Closed arcs wrap at the seam; open ones stop at their ends. */ function normalizeCursorMm(distanceMm, totalLengthMm, closed) { if (!closed) return Math.max(0, Math.min(distanceMm, totalLengthMm)); if (totalLengthMm <= 0) return 0; return (distanceMm % totalLengthMm + totalLengthMm) % totalLengthMm; } /***/ }, /***/ 17924 /*!**************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-config.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CPR_CARRIER_VIEWPORT_IDS: () => (/* binding */ CPR_CARRIER_VIEWPORT_IDS), /* harmony export */ CPR_PANEL_BY_VIEWPORT_ID: () => (/* binding */ CPR_PANEL_BY_VIEWPORT_ID), /* harmony export */ CPR_REQUIRED_CARRIER_ROLES: () => (/* binding */ CPR_REQUIRED_CARRIER_ROLES), /* harmony export */ CPR_WIDTH_MM: () => (/* binding */ CPR_WIDTH_MM), /* harmony export */ CURSOR_GAP_MM: () => (/* binding */ CURSOR_GAP_MM), /* harmony export */ EDIT_NODE_FALLBACK_COLOR: () => (/* binding */ EDIT_NODE_FALLBACK_COLOR), /* harmony export */ EDIT_NODE_FILL_OPACITY: () => (/* binding */ EDIT_NODE_FILL_OPACITY), /* harmony export */ EDIT_NODE_HIT_RADIUS_PX: () => (/* binding */ EDIT_NODE_HIT_RADIUS_PX), /* harmony export */ EDIT_NODE_HOVER_RADIUS_PX: () => (/* binding */ EDIT_NODE_HOVER_RADIUS_PX), /* harmony export */ EDIT_NODE_NEAR_PLANE_MM: () => (/* binding */ EDIT_NODE_NEAR_PLANE_MM), /* harmony export */ EDIT_NODE_RADIUS_PX: () => (/* binding */ EDIT_NODE_RADIUS_PX), /* harmony export */ EDIT_NODE_STROKE_WIDTH_PX: () => (/* binding */ EDIT_NODE_STROKE_WIDTH_PX), /* harmony export */ LONG_AXIS_CAMERA_DISTANCE_MM: () => (/* binding */ LONG_AXIS_CAMERA_DISTANCE_MM), /* harmony export */ RIBBON_ZOOM_RATE_PER_DELTAY: () => (/* binding */ RIBBON_ZOOM_RATE_PER_DELTAY), /* harmony export */ ROTATE_DEG_PER_PX: () => (/* binding */ ROTATE_DEG_PER_PX), /* harmony export */ SHORT_AXIS_FOV_MM: () => (/* binding */ SHORT_AXIS_FOV_MM), /* harmony export */ SHORT_AXIS_INITIAL_POSITION_FRACTION: () => (/* binding */ SHORT_AXIS_INITIAL_POSITION_FRACTION), /* harmony export */ SHORT_AXIS_SCROLL_RATE_MM_PER_DELTAY: () => (/* binding */ SHORT_AXIS_SCROLL_RATE_MM_PER_DELTAY), /* harmony export */ isCprCarrierViewportId: () => (/* binding */ isCprCarrierViewportId) /* harmony export */ }); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../viewport-ids */ 85309); const CPR_CARRIER_VIEWPORT_IDS = { crossSection: 'cprShortAxis', longitudinal: 'cprLongitudinal', ribbonA: 'cprLongAxis', ribbonB: 'cprRibbonB' }; /** The roles a session enables today: one ribbon and the perpendicular cross-section. */ const CPR_REQUIRED_CARRIER_ROLES = ['ribbonA', 'crossSection']; const CARRIER_VIEWPORT_IDS = new Set(Object.values(CPR_CARRIER_VIEWPORT_IDS)); /** * Carriers are orchestrator-unregistered; call sites that walk every engine viewport must * skip them or their state bleeds through (annotation targeting, the global zoom effect). */ function isCprCarrierViewportId(id) { return CARRIER_VIEWPORT_IDS.has(id); } /** * The workspace panel each registered viewport occupies, for workspace-internal maximize. * Only the volume render is shown in the workspace; the three MPRs stay mounted but hidden, * so their own maximize buttons are unreachable and deliberately unmapped. */ const CPR_PANEL_BY_VIEWPORT_ID = { [_viewport_ids__WEBPACK_IMPORTED_MODULE_0__.VIEWPORT_IDS.REFORMAT]: 'reformat' }; /** Radial extent passed to `vtkImageCPRMapper.setWidth`, in millimetres. */ const CPR_WIDTH_MM = 60; /** Long-axis camera-back distance along the ribbon normal, in millimetres. */ const LONG_AXIS_CAMERA_DISTANCE_MM = 100; /** Central gap in the ribbon's cursor cross-bar, in millimetres, keeping the lumen visible. */ const CURSOR_GAP_MM = 16; /** Cut-plane rotation per pixel of radial background drag on the ribbon. */ const ROTATE_DEG_PER_PX = 0.5; /** Ribbon zoom factor per `WheelEvent.deltaY` unit while CTRL is held (or a trackpad pinch). */ const RIBBON_ZOOM_RATE_PER_DELTAY = 1 / 200; /** Short-axis field of view — the resliced output image extent, in millimetres. */ const SHORT_AXIS_FOV_MM = 120; /** Arc-length mm per `WheelEvent.deltaY` unit. */ const SHORT_AXIS_SCROLL_RATE_MM_PER_DELTAY = 1 / 100; /** Initial short-axis position as a fraction of total centerline length (0 = start). */ const SHORT_AXIS_INITIAL_POSITION_FRACTION = 0; /** How far off the cross-section plane a control point may sit and still get a handle, in mm. */ const EDIT_NODE_NEAR_PLANE_MM = 2; const EDIT_NODE_RADIUS_PX = 5; const EDIT_NODE_HOVER_RADIUS_PX = 7; const EDIT_NODE_HIT_RADIUS_PX = 10; const EDIT_NODE_FILL_OPACITY = 0.25; const EDIT_NODE_STROKE_WIDTH_PX = 1.5; const EDIT_NODE_FALLBACK_COLOR = 'var(--p-app-cpr-node-fallback)'; /***/ }, /***/ 72142 /*!***************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-cross-section-overlay.component.ts ***! \***************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprCrossSectionOverlayComponent: () => (/* binding */ CprCrossSectionOverlayComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../window-details/window-details.service */ 99360); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _cpr_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./cpr.service */ 26144); /* harmony import */ var _cross_section_cut_line__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./cross-section-cut-line */ 3832); /* harmony import */ var _cross_section_nodes__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./cross-section-nodes */ 54776); /* harmony import */ var _ribbon_gestures__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ribbon-gestures */ 61193); /** * SVG chrome and pointer surface over the cross-section carrier: the grabbable * cut-line indicator (where the ribbon's rotated plane cuts this slice) and the * wheel scrubbing the cursor along the vessel. Same substrate-free pattern as * the ribbon overlay; CTRL+right-drag W/L bubbles through to the panel. */ const _forTrack0 = ($index, $item) => $item.index; function CprCrossSectionOverlayComponent_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](1, "line", 3); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointerenter", function CprCrossSectionOverlayComponent_Conditional_1_For_2_Template_line_pointerenter_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hover.set(true)); })("pointerleave", function CprCrossSectionOverlayComponent_Conditional_1_For_2_Template_line_pointerleave_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hover.set(false)); })("pointerdown", function CprCrossSectionOverlayComponent_Conditional_1_For_2_Template_line_pointerdown_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.onCutLinePointerDown($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { const segment_r3 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("stroke", ctx_r1.CUT_LINE_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", segment_r3.x1)("y1", segment_r3.y1)("x2", segment_r3.x2)("y2", segment_r3.y2)("stroke-width", ctx_r1.strokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", segment_r3.x1)("y1", segment_r3.y1)("x2", segment_r3.x2)("y2", segment_r3.y2)("stroke-width", ctx_r1.CUT_LINE_HIT_WIDTH_PX); } } function CprCrossSectionOverlayComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterCreate"](1, CprCrossSectionOverlayComponent_Conditional_1_For_2_Template, 2, 12, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterTrackByIndex"]); } if (rf & 2) { const line_r4 = ctx; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("stroke", ctx_r1.CUT_LINE_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", line_r4.gapFill.x1)("y1", line_r4.gapFill.y1)("x2", line_r4.gapFill.x2)("y2", line_r4.gapFill.y2)("stroke-width", ctx_r1.strokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeater"](line_r4.segments); } } function CprCrossSectionOverlayComponent_For_3_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "circle", 4); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](1, "circle", 5); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointerenter", function CprCrossSectionOverlayComponent_For_3_Template_circle_pointerenter_1_listener() { const node_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hoveredNode.set(node_r6.index)); })("pointerleave", function CprCrossSectionOverlayComponent_For_3_Template_circle_pointerleave_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r5); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hoveredNode.set(undefined)); })("pointerdown", function CprCrossSectionOverlayComponent_For_3_Template_circle_pointerdown_1_listener($event) { const node_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r5).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.onNodePointerDown($event, node_r6.index)); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { const node_r6 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("cx", node_r6.x)("cy", node_r6.y)("r", ctx_r1.nodeRadius(node_r6.index))("fill", ctx_r1.nodeColor())("fill-opacity", ctx_r1.EDIT_NODE_FILL_OPACITY)("stroke", ctx_r1.nodeColor())("stroke-width", ctx_r1.EDIT_NODE_STROKE_WIDTH_PX); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("cx", node_r6.x)("cy", node_r6.y)("r", ctx_r1.EDIT_NODE_HIT_RADIUS_PX); } } const CUT_LINE_COLOR = 'var(--p-app-cpr-cut-line)'; const CUT_LINE_HIT_WIDTH_PX = 16; class CprCrossSectionOverlayComponent { CUT_LINE_COLOR = CUT_LINE_COLOR; CUT_LINE_HIT_WIDTH_PX = CUT_LINE_HIT_WIDTH_PX; EDIT_NODE_HIT_RADIUS_PX = _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_HIT_RADIUS_PX; EDIT_NODE_FILL_OPACITY = _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_FILL_OPACITY; EDIT_NODE_STROKE_WIDTH_PX = _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_STROKE_WIDTH_PX; cprService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_cpr_service__WEBPACK_IMPORTED_MODULE_6__.CprService); session = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.cprSessionStore); host = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef).nativeElement; box = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "box" }] : [])); hover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "hover" }] : [])); dragging = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "dragging" }] : [])); drag; crosshairSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.viewportStore).crosshairSize; devicePixelRatio = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_window_details_window_details_service__WEBPACK_IMPORTED_MODULE_4__.WindowDetailsService).devicePixelRatio; strokeWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const base = this.crosshairSize() / this.devicePixelRatio(); return this.hover() || this.dragging() ? base * 2 : base; }, ...(ngDevMode ? [{ debugName: "strokeWidth" }] : [])); hoveredNode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "hoveredNode" }] : [])); draggingNode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "draggingNode" }] : [])); dragPreviewPx = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "dragPreviewPx" }] : [])); dragWorld; nodeColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.cprService.activeSplineColor() ?? _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_FALLBACK_COLOR, ...(ngDevMode ? [{ debugName: "nodeColor" }] : [])); nodes = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { if (this.session.editState() !== 'editing') return []; this.cprService.shortAxisCameraVersion(); const plane = this.cprService.shortAxisPlane(); if (!plane) return []; const points = this.cprService.controlPoints(); const dragging = this.draggingNode(); const preview = this.dragPreviewPx(); return (0,_cross_section_nodes__WEBPACK_IMPORTED_MODULE_8__.nearPlaneNodeIndices)({ focalPoint: plane.focalPoint, grabbedIndex: dragging, normal: plane.normal, points, toleranceMm: _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_NEAR_PLANE_MM }).map(index => { const canvas = index === dragging && preview ? preview : this.cprService.worldToCanvas(points[index]); return canvas ? { index, x: canvas[0], y: canvas[1] } : undefined; }).filter(node => node !== undefined); }, ...(ngDevMode ? [{ debugName: "nodes" }] : [])); nodeRadius(index) { return this.hoveredNode() === index ? _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_HOVER_RADIUS_PX : _cpr_config__WEBPACK_IMPORTED_MODULE_5__.EDIT_NODE_RADIUS_PX; } cutLine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { // The framing doubles as the session-live gate: set at first ribbon framing, // cleared on teardown — no cut line over a dormant carrier. const box = this.box(); if (!this.cprService.ribbonFraming() || !box || box.height <= 0 || box.width <= 0) return; return (0,_cross_section_cut_line__WEBPACK_IMPORTED_MODULE_7__.cutLineGeometry)(box, this.session.rotationDeg()); }, ...(ngDevMode ? [{ debugName: "cutLine" }] : [])); constructor() { const observer = new ResizeObserver(() => { this.box.set({ height: this.host.clientHeight, width: this.host.clientWidth }); }); observer.observe(this.host); // Manual listener: wheel must be non-passive for preventDefault, which an // Angular binding cannot guarantee under a passive-events configuration. const onWheel = event => this.onWheel(event); this.host.addEventListener('wheel', onWheel, { passive: false }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { observer.disconnect(); this.host.removeEventListener('wheel', onWheel); }); } onCutLinePointerDown(event) { if (event.button !== 0) return; const box = this.box(); if (!box) return; event.stopPropagation(); event.target.setPointerCapture?.(event.pointerId); const [x, y] = this.eventPosition(event); this.drag = { startPointerDeg: (0,_cross_section_cut_line__WEBPACK_IMPORTED_MODULE_7__.pointerAngleDeg)(box, x, y), startRotationDeg: this.session.rotationDeg() }; this.dragging.set(true); } onNodePointerDown(event, index) { if (event.button !== 0) return; event.stopPropagation(); event.target.setPointerCapture?.(event.pointerId); // Before the snap, so the grabbed node keeps its handle through the recompute. this.draggingNode.set(index); // Snap the plane onto the node, zeroing its residual off-plane error before it can move. const distanceMm = this.cprService.controlPointDistances()[index]; if (distanceMm !== undefined) this.cprService.jumpCursor(distanceMm); } onPointerMove(event) { if (this.draggingNode() !== undefined) { this.dragNode(event); return; } const drag = this.drag; const box = this.box(); if (!drag || !box) return; const [x, y] = this.eventPosition(event); const deltaDeg = (0,_cross_section_cut_line__WEBPACK_IMPORTED_MODULE_7__.pointerAngleDeg)(box, x, y) - drag.startPointerDeg; this.session.setRotationDeg(Math.round(drag.startRotationDeg + deltaDeg)); } onPointerUp(event) { const index = this.draggingNode(); if (index !== undefined) { const world = this.dragWorld; this.clearNodeDrag(event); // A press that never moved has nothing to commit. if (world) this.cprService.commitControlPointDrag(index, world); return; } this.clearCutLineDrag(event); } // A cancelled stream delivers no pointerup: a stale drag would keep rotating the cut line // with no button pressed, and a cancelled node drag must commit nothing. onPointerCancel(event) { if (this.draggingNode() !== undefined) { this.clearNodeDrag(event); return; } this.clearCutLineDrag(event); } // Previews in pixels and writes no `cursorMm`: the cursor effect never fires, so the plane // cannot chase the very handle it is derived from. dragNode(event) { const index = this.draggingNode(); const nodePosition = index === undefined ? undefined : this.cprService.controlPoints()[index]; const plane = this.cprService.shortAxisPlane(); const onPlane = this.cprService.canvasToWorld(this.eventPosition(event)); if (!nodePosition || !plane || !onPlane) return; this.dragWorld = (0,_cross_section_nodes__WEBPACK_IMPORTED_MODULE_8__.inPlaneDragTarget)({ nodePosition, normal: plane.normal, onPlane }); this.dragPreviewPx.set(this.cprService.worldToCanvas(this.dragWorld)); } clearNodeDrag(event) { (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_9__.releaseCapturedPointer)(event); this.draggingNode.set(undefined); this.dragPreviewPx.set(undefined); this.dragWorld = undefined; } clearCutLineDrag(event) { if (this.drag) (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_9__.releaseCapturedPointer)(event); this.drag = undefined; this.dragging.set(false); } onWheel(event) { if (!this.cprService.ribbonFraming()) return; // The whole surface scrolls, CTRL included — the carrier's old listener made // no modifier distinction and the cross-section has no zoom to give CTRL to. event.preventDefault(); // A scrub mid-drag would move the plane the drag is being measured against. if (this.draggingNode() !== undefined) return; const deltaY = (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_9__.normalizeWheelDeltaY)(event.deltaY, event.deltaMode); this.cprService.scrubCursor(deltaY * _cpr_config__WEBPACK_IMPORTED_MODULE_5__.SHORT_AXIS_SCROLL_RATE_MM_PER_DELTAY); } eventPosition(event) { const rect = this.host.getBoundingClientRect(); return [event.clientX - rect.left, event.clientY - rect.top]; } static ɵfac = function CprCrossSectionOverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CprCrossSectionOverlayComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineComponent"]({ type: CprCrossSectionOverlayComponent, selectors: [["lib-cpr-cross-section-overlay"]], hostAttrs: [1, "absolute", "inset-0", "block"], decls: 4, vars: 1, consts: [[1, "h-full", "w-full", "select-none", 3, "pointermove", "pointerup", "pointercancel", "contextmenu"], ["opacity", "0.25", "pointer-events", "none"], ["data-cut-line", "", "pointer-events", "none"], ["data-cut-line-hit", "", "stroke", "transparent", "pointer-events", "stroke", 3, "pointerenter", "pointerleave", "pointerdown"], ["data-node-handle", "", "pointer-events", "none"], ["data-node-handle-hit", "", "fill", "transparent", "pointer-events", "all", 3, "pointerenter", "pointerleave", "pointerdown"]], template: function CprCrossSectionOverlayComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](0, "svg", 0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointermove", function CprCrossSectionOverlayComponent_Template_svg_pointermove_0_listener($event) { return ctx.onPointerMove($event); })("pointerup", function CprCrossSectionOverlayComponent_Template_svg_pointerup_0_listener($event) { return ctx.onPointerUp($event); })("pointercancel", function CprCrossSectionOverlayComponent_Template_svg_pointercancel_0_listener($event) { return ctx.onPointerCancel($event); })("contextmenu", function CprCrossSectionOverlayComponent_Template_svg_contextmenu_0_listener($event) { return $event.preventDefault(); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditionalCreate"](1, CprCrossSectionOverlayComponent_Conditional_1_Template, 3, 7); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterCreate"](2, CprCrossSectionOverlayComponent_For_3_Template, 2, 10, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { let tmp_0_0; _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditional"]((tmp_0_0 = ctx.cutLine()) ? 1 : -1, tmp_0_0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeater"](ctx.nodes()); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 3338 /*!******************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-image-data.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildCprImageData: () => (/* binding */ buildCprImageData) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/Core/DataArray */ 40928); /* harmony import */ var _kitware_vtk_js_Common_DataModel_ImageData__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/ImageData */ 56394); /** * A private `vtkImageData` for the CPR mapper: the shared volume's geometry with * scalars assembled once from Cornerstone's chunked `voxelManager`. Never hand the * mapper the shared imageData — mutating its `PointData` invalidates every other * viewport's cached volume texture and forces full re-uploads on entry. */ function buildCprImageData(shared) { const voxelManagerHolder = shared.get('voxelManager'); const voxelManager = voxelManagerHolder?.voxelManager; if (!voxelManager) { throw new Error('buildCprImageData: no voxelManager on imageData; ' + 'cannot assemble scalars for the CPR mapper.'); } const copy = _kitware_vtk_js_Common_DataModel_ImageData__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(); copy.setDimensions(shared.getDimensions()); copy.setSpacing(shared.getSpacing()); copy.setOrigin(shared.getOrigin()); copy.setDirection(shared.getDirection()); copy.getPointData().setScalars(_kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ name: 'Scalars', numberOfComponents: voxelManager.numberOfComponents, values: voxelManager.getCompleteScalarDataArray() })); return copy; } /***/ }, /***/ 41326 /*!*******************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-resize-handle.directive.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprResizeHandleDirective: () => (/* binding */ CprResizeHandleDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); /** Drag source for a workspace grid boundary: emits the px delta from where the drag started. */ /** One arrow-key press moves the boundary this far, as a tiny complete drag. */ const KEY_STEP_PX = 16; class CprResizeHandleDirective { axis = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required({ ...(ngDevMode ? { debugName: "axis" } : {}), alias: 'libCprResizeHandle' }); dragStarted = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); dragMoved = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); dragEnded = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); element = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.ElementRef).nativeElement; origin = undefined; onKeyDown(event) { const direction = this.keyDirection(event.key); if (direction === undefined || this.origin !== undefined) return; event.preventDefault(); this.dragStarted.emit(); this.dragMoved.emit(direction * KEY_STEP_PX); this.dragEnded.emit(); } keyDirection(key) { if (this.axis() === 'x') { if (key === 'ArrowLeft') return -1; if (key === 'ArrowRight') return 1; } else { if (key === 'ArrowUp') return -1; if (key === 'ArrowDown') return 1; } return undefined; } onPointerDown(event) { event.preventDefault(); this.origin = this.coordinate(event); // Capture keeps the drag alive over the viewport canvases the handle sits between. this.element.setPointerCapture(event.pointerId); this.dragStarted.emit(); } onPointerMove(event) { if (this.origin === undefined) return; this.dragMoved.emit(this.coordinate(event) - this.origin); } onPointerUp(event) { if (this.origin === undefined) return; this.origin = undefined; this.element.releasePointerCapture(event.pointerId); this.dragEnded.emit(); } coordinate(event) { return this.axis() === 'x' ? event.clientX : event.clientY; } static ɵfac = function CprResizeHandleDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CprResizeHandleDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineDirective"]({ type: CprResizeHandleDirective, selectors: [["", "libCprResizeHandle", ""]], hostAttrs: ["tabindex", "0"], hostBindings: function CprResizeHandleDirective_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("keydown", function CprResizeHandleDirective_keydown_HostBindingHandler($event) { return ctx.onKeyDown($event); })("pointercancel", function CprResizeHandleDirective_pointercancel_HostBindingHandler($event) { return ctx.onPointerUp($event); })("pointerdown", function CprResizeHandleDirective_pointerdown_HostBindingHandler($event) { return ctx.onPointerDown($event); })("pointermove", function CprResizeHandleDirective_pointermove_HostBindingHandler($event) { return ctx.onPointerMove($event); })("pointerup", function CprResizeHandleDirective_pointerup_HostBindingHandler($event) { return ctx.onPointerUp($event); }); } }, inputs: { axis: [1, "libCprResizeHandle", "axis"] }, outputs: { dragStarted: "dragStarted", dragMoved: "dragMoved", dragEnded: "dragEnded" } }); } /***/ }, /***/ 52158 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-ribbon-overlay.component.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprRibbonOverlayComponent: () => (/* binding */ CprRibbonOverlayComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../window-details/window-details.service */ 99360); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _cpr_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./cpr.service */ 26144); /* harmony import */ var _long_axis_camera__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./long-axis-camera */ 51984); /* harmony import */ var _ribbon_cursor__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ribbon-cursor */ 36955); /* harmony import */ var _ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ribbon-gestures */ 61193); /* harmony import */ var _ribbon_projection__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ribbon-projection */ 94212); /* harmony import */ var _ribbon_ruler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./ribbon-ruler */ 15701); /** * SVG chrome and pointer surface over the ribbon carrier, projected through the * framing `CprService` publishes — never the camera. Owns every left-button and * wheel gesture on the ribbon; the panel's CTRL+right-drag W/L reaches its * handlers by bubbling. */ const _forTrack0 = ($index, $item) => $item.d + ($item.seam ? "-seam" : ""); const _forTrack1 = ($index, $item) => $item.index; function CprRibbonOverlayComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 1); } if (rf & 2) { const trace_r1 = ctx; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", trace_r1.x1)("y1", trace_r1.y1)("x2", trace_r1.x2)("y2", trace_r1.y2)("stroke", ctx_r1.nodeColor())("stroke-dasharray", ctx_r1.TRACE_DASH_ARRAY)("opacity", ctx_r1.TRACE_OPACITY); } } function CprRibbonOverlayComponent_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](0, "text", 4); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { const tick_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("fill", tick_r3.seam ? ctx_r1.SEAM_COLOR : ctx_r1.LABEL_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x", tick_r3.labelX)("y", tick_r3.labelY); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵtextInterpolate1"](" ", tick_r3.seam ? _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵpipeBind1"](2, 5, "planarReformation.seam") : tick_r3.label, " "); } } function CprRibbonOverlayComponent_For_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditionalCreate"](1, CprRibbonOverlayComponent_For_3_Conditional_1_Template, 3, 7, ":svg:text", 3); } if (rf & 2) { const tick_r3 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("stroke", tick_r3.seam ? ctx_r1.SEAM_COLOR : ctx_r1.TICK_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", tick_r3.x1)("y1", tick_r3.y1)("x2", tick_r3.x2)("y2", tick_r3.y2)("stroke-width", tick_r3.seam ? 2 : 1); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditional"](tick_r3.seam || tick_r3.label ? 1 : -1); } } function CprRibbonOverlayComponent_For_5_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "circle", 5); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](1, "circle", 6); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointerenter", function CprRibbonOverlayComponent_For_5_Template_circle_pointerenter_1_listener() { const marker_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hoveredNode.set(marker_r5.index)); })("pointerleave", function CprRibbonOverlayComponent_For_5_Template_circle_pointerleave_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.hoveredNode.set(undefined)); })("pointerdown", function CprRibbonOverlayComponent_For_5_Template_circle_pointerdown_1_listener($event) { const marker_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r4).$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.onNodeMarkerPointerDown($event, marker_r5.d)); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { const marker_r5 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("cx", marker_r5.x)("cy", marker_r5.y)("r", ctx_r1.markerRadius(marker_r5.index))("fill", ctx_r1.nodeColor())("fill-opacity", ctx_r1.EDIT_NODE_FILL_OPACITY)("stroke", ctx_r1.nodeColor())("stroke-width", ctx_r1.EDIT_NODE_STROKE_WIDTH_PX); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("cx", marker_r5.x)("cy", marker_r5.y)("r", ctx_r1.EDIT_NODE_HIT_RADIUS_PX); } } function CprRibbonOverlayComponent_Conditional_6_For_2_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 8); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](1, "line", 9); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointerenter", function CprRibbonOverlayComponent_Conditional_6_For_2_Template_line_pointerenter_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.cursorHover.set(true)); })("pointerleave", function CprRibbonOverlayComponent_Conditional_6_For_2_Template_line_pointerleave_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.cursorHover.set(false)); })("pointerdown", function CprRibbonOverlayComponent_Conditional_6_For_2_Template_line_pointerdown_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r1.onCursorPointerDown($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { const segment_r7 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("stroke", ctx_r1.CURSOR_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", segment_r7.x1)("y1", segment_r7.y1)("x2", segment_r7.x2)("y2", segment_r7.y2)("stroke-width", ctx_r1.cursorStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", segment_r7.x1)("y1", segment_r7.y1)("x2", segment_r7.x2)("y2", segment_r7.y2)("stroke-width", ctx_r1.CURSOR_HIT_WIDTH_PX); } } function CprRibbonOverlayComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElement"](0, "line", 7); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterCreate"](1, CprRibbonOverlayComponent_Conditional_6_For_2_Template, 2, 12, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterTrackByIndex"]); } if (rf & 2) { const bar_r8 = ctx; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵstyleProp"]("stroke", ctx_r1.CURSOR_COLOR); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵattribute"]("x1", bar_r8.gapFill.x1)("y1", bar_r8.gapFill.y1)("x2", bar_r8.gapFill.x2)("y2", bar_r8.gapFill.y2)("stroke-width", ctx_r1.cursorStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeater"](bar_r8.segments); } } const TICK_COLOR = 'var(--p-app-cpr-tick)'; const LABEL_COLOR = 'var(--p-app-cpr-label)'; const SEAM_COLOR = 'var(--p-app-cpr-seam)'; const CURSOR_COLOR = 'var(--p-app-cpr-cursor)'; const CURSOR_HIT_WIDTH_PX = 16; const TRACE_DASH_ARRAY = '5 4'; const TRACE_OPACITY = 0.6; class CprRibbonOverlayComponent { TICK_COLOR = TICK_COLOR; LABEL_COLOR = LABEL_COLOR; SEAM_COLOR = SEAM_COLOR; CURSOR_COLOR = CURSOR_COLOR; CURSOR_HIT_WIDTH_PX = CURSOR_HIT_WIDTH_PX; TRACE_DASH_ARRAY = TRACE_DASH_ARRAY; TRACE_OPACITY = TRACE_OPACITY; EDIT_NODE_HIT_RADIUS_PX = _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_HIT_RADIUS_PX; EDIT_NODE_FILL_OPACITY = _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_FILL_OPACITY; EDIT_NODE_STROKE_WIDTH_PX = _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_STROKE_WIDTH_PX; cprService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_cpr_service__WEBPACK_IMPORTED_MODULE_7__.CprService); session = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.cprSessionStore); host = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef).nativeElement; box = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "box" }] : [])); cursorHover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "cursorHover" }] : [])); hoveredNode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, ...(ngDevMode ? [{ debugName: "hoveredNode" }] : [])); draggingCursor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "draggingCursor" }] : [])); backgroundGesture; crosshairSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore).crosshairSize; devicePixelRatio = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_window_details_window_details_service__WEBPACK_IMPORTED_MODULE_5__.WindowDetailsService).devicePixelRatio; cursorStrokeWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const base = this.crosshairSize() / this.devicePixelRatio(); return this.cursorHover() || this.draggingCursor() ? base * 2 : base; }, ...(ngDevMode ? [{ debugName: "cursorStrokeWidth" }] : [])); ticks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const framing = this.cprService.ribbonFraming(); const box = this.box(); if (!framing || !box || box.height <= 0 || box.width <= 0) return []; const closed = this.cprService.activeSplineIsClosed(); return (0,_ribbon_ruler__WEBPACK_IMPORTED_MODULE_12__.rulerTicks)(framing.ribbonLengthMm, closed).map(tick => (0,_ribbon_ruler__WEBPACK_IMPORTED_MODULE_12__.projectRulerTick)(framing, box, tick)); }, ...(ngDevMode ? [{ debugName: "ticks" }] : [])); nodeColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.cprService.activeSplineColor() ?? _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_FALLBACK_COLOR, ...(ngDevMode ? [{ debugName: "nodeColor" }] : [])); // Straightening puts the centerline at lambda = 0, so the trace is one straight line. centerlineTrace = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { if (this.session.editState() !== 'editing') return; const framing = this.cprService.ribbonFraming(); const box = this.box(); if (!framing || !box || box.height <= 0 || box.width <= 0) return; const [x1, y1] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_11__.ribbonToCanvas)(framing, box, { d: 0, lambda: 0 }); const [x2, y2] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_11__.ribbonToCanvas)(framing, box, { d: framing.ribbonLengthMm, lambda: 0 }); return { x1, x2, y1, y2 }; }, ...(ngDevMode ? [{ debugName: "centerlineTrace" }] : [])); nodeMarkers = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { if (this.session.editState() !== 'editing') return []; const framing = this.cprService.ribbonFraming(); const box = this.box(); if (!framing || !box || box.height <= 0 || box.width <= 0) return []; return this.cprService.controlPointDistances().map((d, index) => { const [x, y] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_11__.ribbonToCanvas)(framing, box, { d, lambda: 0 }); return { d, index, x, y }; }); }, ...(ngDevMode ? [{ debugName: "nodeMarkers" }] : [])); markerRadius(index) { return this.hoveredNode() === index ? _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_HOVER_RADIUS_PX : _cpr_config__WEBPACK_IMPORTED_MODULE_6__.EDIT_NODE_RADIUS_PX; } crossBar = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const framing = this.cprService.ribbonFraming(); const box = this.box(); if (!framing || !box || box.height <= 0 || box.width <= 0) return; return (0,_ribbon_cursor__WEBPACK_IMPORTED_MODULE_9__.cursorCrossBar)(framing, box, this.session.cursorMm()); }, ...(ngDevMode ? [{ debugName: "crossBar" }] : [])); constructor() { const observer = new ResizeObserver(() => { this.box.set({ height: this.host.clientHeight, width: this.host.clientWidth }); }); observer.observe(this.host); // Manual listener: wheel must be non-passive for preventDefault, which an // Angular binding cannot guarantee under a passive-events configuration. const onWheel = event => this.onWheel(event); this.host.addEventListener('wheel', onWheel, { passive: false }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { observer.disconnect(); this.host.removeEventListener('wheel', onWheel); }); } /** Grab of the cross-bar: the drag scrubs the cursor along the arc. */ onCursorPointerDown(event) { if (event.button !== 0) return; event.stopPropagation(); event.target.setPointerCapture?.(event.pointerId); this.draggingCursor.set(true); } onNodeMarkerPointerDown(event, d) { if (event.button !== 0) return; event.stopPropagation(); this.cprService.jumpCursor(d); } /** Background press: a still click jumps the cursor; a radial drag rotates the cut plane. */ onSvgPointerDown(event) { if (event.button !== 0) return; event.target.setPointerCapture?.(event.pointerId); this.backgroundGesture = { moved: false, startRotationDeg: this.session.rotationDeg(), startX: event.clientX, startY: event.clientY }; } onSvgPointerMove(event) { if (this.draggingCursor()) { this.scrubToEvent(event); return; } const gesture = this.backgroundGesture; if (!gesture) return; if (!gesture.moved && (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__.exceedsStillClick)(gesture.startX, gesture.startY, event.clientX, event.clientY)) { gesture.moved = true; } if (gesture.moved) { // Rotation reads the radial screen axis: across the ribbon, whichever way it lies. const radialPx = this.session.orientation() === 'vertical' ? event.clientX - gesture.startX : event.clientY - gesture.startY; this.session.setRotationDeg(Math.round(gesture.startRotationDeg + radialPx * _cpr_config__WEBPACK_IMPORTED_MODULE_6__.ROTATE_DEG_PER_PX)); } } onSvgPointerUp(event) { (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__.releaseCapturedPointer)(event); if (this.draggingCursor()) { this.draggingCursor.set(false); return; } const gesture = this.backgroundGesture; this.backgroundGesture = undefined; if (gesture && !gesture.moved) this.scrubToEvent(event); } // A cancelled pointer stream delivers no pointerup; without this the next // hover would keep scrubbing or rotating with no button pressed. onSvgPointerCancel(event) { (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__.releaseCapturedPointer)(event); this.draggingCursor.set(false); this.backgroundGesture = undefined; } onWheel(event) { if (!this.cprService.ribbonFraming()) return; event.preventDefault(); const deltaY = (0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__.normalizeWheelDeltaY)(event.deltaY, event.deltaMode); if (event.ctrlKey) { // CTRL+wheel and trackpad pinch (which arrives as a CTRL wheel) zoom the ribbon. const factor = Math.exp(-deltaY * _cpr_config__WEBPACK_IMPORTED_MODULE_6__.RIBBON_ZOOM_RATE_PER_DELTAY); this.session.setRibbonZoom((0,_long_axis_camera__WEBPACK_IMPORTED_MODULE_8__.clampRibbonZoom)(this.session.ribbonZoom() * factor)); return; } this.cprService.scrubCursor((0,_ribbon_gestures__WEBPACK_IMPORTED_MODULE_10__.wheelCursorStepMm)(deltaY, event.shiftKey)); } scrubToEvent(event) { const framing = this.cprService.ribbonFraming(); const box = this.box(); if (!framing || !box) return; const rect = this.host.getBoundingClientRect(); const point = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_11__.canvasToRibbon)(framing, box, event.clientX - rect.left, event.clientY - rect.top); this.cprService.setCursor(point.d); } static ɵfac = function CprRibbonOverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CprRibbonOverlayComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineComponent"]({ type: CprRibbonOverlayComponent, selectors: [["lib-cpr-ribbon-overlay"]], hostAttrs: [1, "absolute", "inset-0", "block"], decls: 7, vars: 2, consts: [[1, "h-full", "w-full", "select-none", 3, "pointerdown", "pointermove", "pointerup", "pointercancel", "contextmenu"], ["data-centerline-trace", "", "stroke-width", "1", "pointer-events", "none"], ["data-ruler-tick", "", "pointer-events", "none"], ["font-size", "11", "font-weight", "600", "pointer-events", "none", 1, "text-shadow-[0_0_3px_var(--p-app-viewport-outline),0_0_3px_var(--p-app-viewport-outline)]", 3, "fill"], ["font-size", "11", "font-weight", "600", "pointer-events", "none", 1, "text-shadow-[0_0_3px_var(--p-app-viewport-outline),0_0_3px_var(--p-app-viewport-outline)]"], ["data-ribbon-node", "", "pointer-events", "none"], ["data-ribbon-node-hit", "", "fill", "transparent", "pointer-events", "all", 3, "pointerenter", "pointerleave", "pointerdown"], ["opacity", "0.25", "pointer-events", "none"], ["data-cursor-line", "", "pointer-events", "none"], ["data-cursor-hit", "", "stroke", "transparent", "pointer-events", "stroke", 3, "pointerenter", "pointerleave", "pointerdown"]], template: function CprRibbonOverlayComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementStart"](0, "svg", 0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomListener"]("pointerdown", function CprRibbonOverlayComponent_Template_svg_pointerdown_0_listener($event) { return ctx.onSvgPointerDown($event); })("pointermove", function CprRibbonOverlayComponent_Template_svg_pointermove_0_listener($event) { return ctx.onSvgPointerMove($event); })("pointerup", function CprRibbonOverlayComponent_Template_svg_pointerup_0_listener($event) { return ctx.onSvgPointerUp($event); })("pointercancel", function CprRibbonOverlayComponent_Template_svg_pointercancel_0_listener($event) { return ctx.onSvgPointerCancel($event); })("contextmenu", function CprRibbonOverlayComponent_Template_svg_contextmenu_0_listener($event) { return $event.preventDefault(); }); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditionalCreate"](1, CprRibbonOverlayComponent_Conditional_1_Template, 1, 7, ":svg:line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterCreate"](2, CprRibbonOverlayComponent_For_3_Template, 2, 8, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeaterCreate"](4, CprRibbonOverlayComponent_For_5_Template, 2, 10, null, null, _forTrack1); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditionalCreate"](6, CprRibbonOverlayComponent_Conditional_6_Template, 3, 7); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdomElementEnd"](); } if (rf & 2) { let tmp_0_0; let tmp_3_0; _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditional"]((tmp_0_0 = ctx.centerlineTrace()) ? 1 : -1, tmp_0_0); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeater"](ctx.ticks()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrepeater"](ctx.nodeMarkers()); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵconditional"]((tmp_3_0 = ctx.crossBar()) ? 6 : -1, tmp_3_0); } }, dependencies: [_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 87660 /*!****************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-viewport.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprViewport: () => (/* binding */ CprViewport) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Renderer */ 45471); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const WIDGET_ID_PREFIX = 'tomoverse:cpr-viewport:'; class CprViewport { host; renderer; renderWindow; widgetId; actorsByUid = new Map(); disposed = false; constructor(host, slot) { this.host = host; const primary = host.getRenderer?.(); const renderWindow = primary?.getRenderWindow?.(); if (!primary || !renderWindow) { throw new Error(`CprViewport: host viewport ${host.id} has no renderer or render window`); } this.renderWindow = renderWindow; this.widgetId = `${WIDGET_ID_PREFIX}${slot}`; this.renderer = _kitware_vtk_js_Rendering_Core_Renderer__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); this.renderer.setBackground(0, 0, 0); // Added after the host's primary ⇒ we render last in layer 0 and overwrite it. renderWindow.addRenderer(this.renderer); this.renderer.setLayer(0); // The engine's per-pass loop (getWidgetRenderers) flips this on only during // the host's pass. this.renderer.setDraw(false); this.syncViewportRectFromPrimary(); const widget = { getActor: () => { // Returning nothing short-circuits Cornerstone's `removeWidgets` cleanup. }, getEnabled: () => !this.disposed, getRenderer: () => { if (this.disposed) return; this.syncViewportRectFromPrimary(); return this.renderer; }, setEnabled: () => { // No-op: enabled state derives from `disposed` (see getEnabled). } }; host.addWidget(this.widgetId, widget); } get camera() { return this.renderer.getActiveCamera(); } setActors(actors) { if (this.disposed) return; const incomingUids = new Set(actors.map(a => a.uid)); for (const [uid, existing] of this.actorsByUid) { if (!incomingUids.has(uid)) { this.renderer.removeActor(existing); this.actorsByUid.delete(uid); } } for (const { actor, uid } of actors) { this.addActor(uid, actor); } } addActor(uid, actor) { if (this.disposed) return; const previous = this.actorsByUid.get(uid); if (previous === actor) return; if (previous) this.renderer.removeActor(previous); this.renderer.addActor(actor); this.actorsByUid.set(uid, actor); } removeActor(uid) { if (this.disposed) return; const existing = this.actorsByUid.get(uid); if (!existing) return; this.renderer.removeActor(existing); this.actorsByUid.delete(uid); } resetCamera() { if (this.disposed) return; this.renderer.resetCamera(); this.requestRender(); } requestRender() { if (this.disposed) return; this.host.render(); } dispose() { if (this.disposed) return; this.disposed = true; for (const [, actor] of this.actorsByUid) { this.renderer.removeActor(actor); } this.actorsByUid.clear(); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.removeViewportWidget)(this.host, this.widgetId); this.renderWindow.removeRenderer?.(this.renderer); this.renderer.delete?.(); } syncViewportRectFromPrimary() { const rect = this.primaryViewportRect(); if (rect) { this.renderer.setViewport(...rect); } } primaryViewportRect() { try { return this.host.getRenderer?.()?.getViewport?.(); } catch { // The host stops resolving a renderer once its engine starts tearing down. return undefined; } } } /***/ }, /***/ 11095 /*!***************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr-workspace.component.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprWorkspaceComponent: () => (/* binding */ CprWorkspaceComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../viewport-interaction/viewport-interaction.service */ 46184); /* harmony import */ var _control_point_step__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./control-point-step */ 85367); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _cpr_cross_section_overlay_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./cpr-cross-section-overlay.component */ 72142); /* harmony import */ var _cpr_resize_handle_directive__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./cpr-resize-handle.directive */ 41326); /* harmony import */ var _cpr_ribbon_overlay_component__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./cpr-ribbon-overlay.component */ 52158); /* harmony import */ var _cpr_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./cpr.service */ 26144); /* harmony import */ var _grid_fractions__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./grid-fractions */ 87242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @angular/core */ 14975); /** * The curved-MPR workspace: a resizable CSS grid holding the CPR carrier mounts and the * registered viewports projected in from the viewer, plus the carrier container wiring * `CprService` gates its session on. */ const _c0 = ["workspaceGrid"]; const _c1 = ["middleColumn"]; const _c2 = ["cprLongAxisContainer"]; const _c3 = ["cprShortAxisContainer"]; const _c4 = (a0, a1) => ({ "animate-viewport-blur-in": a0, "animate-viewport-blur-out": a1 }); const _c5 = () => ({ $implicit: "ribbon" }); const _c6 = () => ({ $implicit: "crossSection" }); const _c7 = (a0, a1) => ({ $implicit: a0, name: a1, panel: "reformat", area: "1 / 3" }); const _c8 = () => ({ $implicit: "x", group: "columns", boundary: 0 }); const _c9 = () => ({ $implicit: "y", group: "middleRows", boundary: 0 }); const _c10 = () => ({ $implicit: "x", group: "topColumns", boundary: 0, area: "1 / 2" }); const _c11 = () => ({ $implicit: "y", group: "bodyRows", boundary: 0, area: "2 / 1 / 3 / -1" }); function CprWorkspaceComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "lib-viewport-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("click", function CprWorkspaceComponent_Conditional_6_Template_lib_viewport_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.confirmEdit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](3, "lib-viewport-button", 22); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("click", function CprWorkspaceComponent_Conditional_6_Template_lib_viewport_button_click_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.cancelEdit()); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](1, 4, "planarReformation.confirmEdit"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](2, 6, "planarReformation.confirmEdit")); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](4, 8, "planarReformation.cancelEdit"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](5, 10, "planarReformation.cancelEdit")); } } function CprWorkspaceComponent_ng_container_15_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_16_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](0, CprWorkspaceComponent_Conditional_16_ng_container_0_Template, 1, 0, "ng-container", 15); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); const handle_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵreference"](33); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", handle_r4)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](2, _c8)); } } function CprWorkspaceComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelement"](0, "img", 18); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("src", ctx, _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵsanitizeUrl"]); } } function CprWorkspaceComponent_ng_container_26_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_27_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](0, CprWorkspaceComponent_Conditional_27_ng_container_0_Template, 1, 0, "ng-container", 15); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); const handle_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵreference"](33); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", handle_r4)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](2, _c9)); } } function CprWorkspaceComponent_ng_container_28_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_29_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_29_ng_container_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](0, CprWorkspaceComponent_Conditional_29_ng_container_0_Template, 1, 0, "ng-container", 15)(1, CprWorkspaceComponent_Conditional_29_ng_container_1_Template, 1, 0, "ng-container", 15); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); const handle_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵreference"](33); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", handle_r4)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](4, _c10)); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", handle_r4)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](5, _c11)); } } function CprWorkspaceComponent_ng_template_30_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_ng_template_30_Conditional_4_ng_container_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_ng_template_30_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "div", 25); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](1, CprWorkspaceComponent_ng_template_30_Conditional_4_ng_container_1_Template, 1, 0, "ng-container", 20); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", ctx); } } function CprWorkspaceComponent_ng_template_30_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "div", 23)(1, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](2, CprWorkspaceComponent_ng_template_30_ng_container_2_Template, 1, 0, "ng-container", 20); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelement"](3, "lib-viewport-indicator", 24); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](4, CprWorkspaceComponent_ng_template_30_Conditional_4_Template, 2, 1, "div", 25); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_23_0; const viewportTemplate_r5 = ctx.$implicit; const name_r6 = ctx.name; const panel_r7 = ctx.panel; const area_r8 = ctx.area; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("grid-area", ctx_r2.panelArea(panel_r7, area_r8))("visibility", ctx_r2.panelHidden(panel_r7) ? "hidden" : null)("position", ctx_r2.panelMaximized(panel_r7) ? "absolute" : null)("inset", ctx_r2.panelMaximized(panel_r7) ? "0" : null); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵattribute"]("data-viewport", name_r6); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction2"](16, _c4, ctx_r2.isBlur(), !ctx_r2.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", viewportTemplate_r5); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("viewportName", name_r6)("focusedViewport", ctx_r2.selectedMPRViewport())("initialState", ctx_r2.isInitialViewportState())("lastFocused", ctx_r2.lastSelectedMPRViewport()); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"]((tmp_23_0 = !ctx_r2.horizontal() && !ctx_r2.maximizedPanel() && panel_r7 === "reformat" && ctx_r2.cameraSliderTemplate()) ? 4 : -1, tmp_23_0); } } function CprWorkspaceComponent_ng_template_32_Template(rf, ctx) { if (rf & 1) { const _r9 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "div", 26); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("dragStarted", function CprWorkspaceComponent_ng_template_32_Template_div_dragStarted_0_listener() { const ctx_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r9); const group_r11 = ctx_r9.group; const boundary_r12 = ctx_r9.boundary; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.startTrackDrag(group_r11, boundary_r12)); })("dragMoved", function CprWorkspaceComponent_ng_template_32_Template_div_dragMoved_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r9); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.moveTrackDrag($event)); })("dragEnded", function CprWorkspaceComponent_ng_template_32_Template_div_dragEnded_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r9); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.endTrackDrag()); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); } if (rf & 2) { const axis_r13 = ctx.$implicit; const group_r11 = ctx.group; const boundary_r12 = ctx.boundary; const area_r14 = ctx.area; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("grid-area", area_r14)("visibility", ctx_r2.maximizedPanel() ? "hidden" : null); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵclassProp"]("cursor-col-resize", axis_r13 === "x")("cursor-row-resize", axis_r13 === "y"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("libCprResizeHandle", axis_r13); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵattribute"]("aria-orientation", axis_r13 === "x" ? "vertical" : "horizontal")("aria-valuenow", ctx_r2.boundarySharePercent(group_r11, boundary_r12))("aria-valuemin", ctx_r2.minSharePercent)("aria-valuemax", ctx_r2.maxSharePercent); } } function CprWorkspaceComponent_ng_template_34_Template(rf, ctx) { if (rf & 1) { const _r15 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "div", 27)(1, "lib-viewport-button", 28); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("click", function CprWorkspaceComponent_ng_template_34_Template_lib_viewport_button_click_1_listener() { const panel_r16 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r15).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.toggleMaximized(panel_r16)); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"]()(); } if (rf & 2) { const panel_r16 = ctx.$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("icon", ctx_r2.maximizedPanel() === panel_r16 ? "arrow-down-left-and-arrow-up-right-to-center" : "arrow-up-right-and-arrow-down-left-from-center")("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](2, 4, ctx_r2.maximizedPanel() === panel_r16 ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](3, 6, ctx_r2.maximizedPanel() === panel_r16 ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel")); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵattribute"]("data-test-id", "cpr-lib-viewport-button-maximize-" + panel_r16); } } function CprWorkspaceComponent_ng_container_37_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_ng_container_38_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } function CprWorkspaceComponent_ng_container_39_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementContainer"](0); } } const RIGHT_MOUSE_BUTTON = 2; const STEP_DURATION_MS = 350; function stepDirection(key) { if (key === 'ArrowRight' || key === 'd') return 1; if (key === 'ArrowLeft' || key === 'a') return -1; return undefined; } class CprWorkspaceComponent { ViewportName = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.ViewportName; axialTemplate = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "axialTemplate" }] : [])); coronalTemplate = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "coronalTemplate" }] : [])); reformatTemplate = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "reformatTemplate" }] : [])); sagittalTemplate = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "sagittalTemplate" }] : [])); // The app page's camera slider docks on the volume panel — the only view here it drives. cameraSliderTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(...(ngDevMode ? [undefined, { debugName: "cameraSliderTemplate" }] : [])); isBlur = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "isBlur" }] : [])); isInitialViewportState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, ...(ngDevMode ? [{ debugName: "isInitialViewportState" }] : [])); lastSelectedMPRViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "lastSelectedMPRViewport" }] : [])); selectedMPRViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "selectedMPRViewport" }] : [])); resizeStart = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); resizeEnd = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); // A still of the short-axis held over the live view during resize, so the engine's // rescale-during-drag doesn't flicker through. shortAxisFrozenFrame = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(undefined, ...(ngDevMode ? [{ debugName: "shortAxisFrozenFrame" }] : [])); session = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.cprSessionStore); horizontal = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.session.orientation() === 'horizontal', ...(ngDevMode ? [{ debugName: "horizontal" }] : [])); maximizedPanel = this.session.maximizedPanel; splineName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.cprService.activeSplineName(), ...(ngDevMode ? [{ debugName: "splineName" }] : [])); editing = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.session.editState() === 'editing', ...(ngDevMode ? [{ debugName: "editing" }] : [])); fractions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.session.fractions()[this.session.orientation()], ...(ngDevMode ? [{ debugName: "fractions" }] : [])); columnTracks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.trackList)(this.horizontal() ? this.fractions().topColumns : this.fractions().columns), ...(ngDevMode ? [{ debugName: "columnTracks" }] : [])); rowTracks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.horizontal() ? (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.trackList)(this.fractions().bodyRows) : 'minmax(0,1fr)', ...(ngDevMode ? [{ debugName: "rowTracks" }] : [])); middleRowTracks = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.trackList)(this.fractions().middleRows), ...(ngDevMode ? [{ debugName: "middleRowTracks" }] : [])); cprService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_cpr_service__WEBPACK_IMPORTED_MODULE_15__.CprService); interaction = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_9__.ViewportInteractionService); workspaceGrid = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('workspaceGrid'); middleColumn = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('middleColumn'); longAxisContainer = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('cprLongAxisContainer'); shortAxisContainer = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('cprShortAxisContainer'); drag = undefined; mountResize = undefined; stepRaf = 0; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const mounts = this.carrierMounts(); for (const [role, mount] of mounts) this.cprService.registerCarrierContainer(role, mount); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.untracked)(() => this.observeMounts(mounts.map(([, mount]) => mount))); }); // Re-flowing the same panels changes every carrier's box, so run the resize contract — // orientation is set from the sidebar panel and maximize from the viewports' own buttons. let framed = false; (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { this.session.orientation(); this.session.maximizedPanel(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.untracked)(() => { if (framed) { this.resizeStart.emit(); this.resizeEnd.emit(); } framed = true; }); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { if (this.session.editState() !== 'editing') (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.untracked)(() => this.cancelStep()); }); const onKeyDown = event => this.onKeyDown(event); globalThis.addEventListener('keydown', onKeyDown); // Leaving CPR destroys this component; the service's readiness gate must not keep // a detached mount alive. Static roles, not carrierMounts(): the view queries can // already be unavailable here and a required read would throw. (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.DestroyRef).onDestroy(() => { this.mountResize?.disconnect(); globalThis.removeEventListener('keydown', onKeyDown); this.cancelStep(); for (const role of _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_REQUIRED_CARRIER_ROLES) this.cprService.unregisterCarrierContainer(role); }); } onKeyDown(event) { if (this.session.editState() !== 'editing') return; // The resize handles step with the arrows too; whatever is nearer the focus owns the key. if (event.defaultPrevented || (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.isEditableTarget)(event.target)) return; const direction = stepDirection(event.key); if (!direction) return; event.preventDefault(); // One step per animation: a press mid-tween restarts it from further along and never arrives. if (this.stepRaf) return; this.stepControlPoint(direction); } stepControlPoint(direction) { const closed = this.cprService.activeSplineIsClosed(); const totalLengthMm = this.cprService.centerlineLengthMm(); const fromMm = this.session.cursorMm(); const deltaMm = (0,_control_point_step__WEBPACK_IMPORTED_MODULE_10__.controlPointStepDelta)({ closed, cursorMm: fromMm, direction, distancesMm: this.cprService.controlPointDistances(), totalLengthMm }); if (deltaMm === undefined) return; this.animateStep({ closed, deltaMm, fromMm, totalLengthMm }); } animateStep(input) { const { closed, deltaMm, fromMm, totalLengthMm } = input; this.cancelStep(); const startedAt = performance.now(); const tick = now => { const progress = Math.min(1, (now - startedAt) / STEP_DURATION_MS); const eased = 1 - (1 - progress) ** 3; this.cprService.setCursor((0,_control_point_step__WEBPACK_IMPORTED_MODULE_10__.normalizeCursorMm)(fromMm + deltaMm * eased, totalLengthMm, closed)); this.stepRaf = progress < 1 ? requestAnimationFrame(tick) : 0; }; this.stepRaf = requestAnimationFrame(tick); } cancelStep() { cancelAnimationFrame(this.stepRaf); this.stepRaf = 0; } carrierMounts() { return [['ribbonA', this.longAxisContainer().nativeElement], ['crossSection', this.shortAxisContainer().nativeElement]]; } freezeShortAxis() { const canvas = this.shortAxisContainer().nativeElement.querySelector('canvas'); if (!canvas) return; try { this.shortAxisFrozenFrame.set(canvas.toDataURL()); } catch { // Snapshot unavailable (e.g. empty/tainted canvas); fall back to the live view. } } unfreezeShortAxis() { this.shortAxisFrozenFrame.set(undefined); } panelArea(panel, horizontalArea) { return this.horizontal() ? horizontalArea : undefined; } minSharePercent = _grid_fractions__WEBPACK_IMPORTED_MODULE_16__.MIN_TRACK_SHARE * 100; maxSharePercent = 100 - _grid_fractions__WEBPACK_IMPORTED_MODULE_16__.MIN_TRACK_SHARE * 100; boundarySharePercent(group, boundary) { return (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.trackSharePercent)(this.fractions()[group], boundary); } /** * Maximize lifts the panel out of the grid rather than spanning it: in the vertical * arrangement the MPRs sit inside a column wrapper, where a full-grid span would only * cover that column. Absolute against the workspace host covers everything, both * orientations, without disturbing the tracks the other panels still occupy. */ panelMaximized(panel) { return this.maximizedPanel() === panel; } panelHidden(panel) { const maximized = this.maximizedPanel(); return maximized !== undefined && maximized !== panel; } /** * CTRL + right-drag is the app's W/L gesture; the carriers get it through the same * interaction instance the MPRs use, so the feel and the clamping are shared. */ startWindowDrag(event) { if (event.button !== RIGHT_MOUSE_BUTTON || !event.ctrlKey) return; event.preventDefault(); this.interaction.startWindowSettingsDrag([event.offsetX, event.offsetY]); } updateWindowDrag(event, role) { this.interaction.updateWindowSettingsDrag([event.offsetX, event.offsetY], _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS[role]); } toggleMaximized(panel) { this.session.toggleMaximizedPanel(panel); } exitWorkspace() { this.cprService.cancel(); } confirmEdit() { this.cprService.confirmEdit(); } cancelEdit() { this.cprService.cancelEdit(); } // The carriers' cameras are fixed in mm, so every change of their box — grid re-flow, // window resize, handle drag — has to re-impose the FOV the engine's resize rescaled. observeMounts(mounts) { this.mountResize?.disconnect(); this.mountResize = new ResizeObserver(() => { this.cprService.refreshShortAxisCamera(); this.cprService.refreshLongAxisCamera(); }); for (const mount of mounts) this.mountResize.observe(mount); } startTrackDrag(group, boundary) { const { axis, container } = this.trackGroup(group); const fractions = this.fractions()[group]; const containerPx = axis === 'x' ? container.clientWidth : container.clientHeight; this.drag = { availablePx: (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.availableTrackPx)(containerPx, fractions.length), boundary, fractions, group }; this.resizeStart.emit(); } // Deltas are measured from the drag origin, so they apply to the fractions as captured. moveTrackDrag(deltaPx) { if (!this.drag) return; const { availablePx, boundary, fractions, group } = this.drag; this.session.setTrackFractions(this.session.orientation(), group, (0,_grid_fractions__WEBPACK_IMPORTED_MODULE_16__.resizeTracks)(fractions, boundary, deltaPx, availablePx)); } endTrackDrag() { if (!this.drag) return; this.drag = undefined; this.resizeEnd.emit(); } // Horizontal's tracks all belong to the workspace grid itself; vertical's row groups // belong to the column wrappers, which is why those keep a box in that orientation. trackGroup(group) { switch (group) { case 'bodyRows': { return { axis: 'y', container: this.workspaceGrid().nativeElement }; } case 'columns': case 'topColumns': { return { axis: 'x', container: this.workspaceGrid().nativeElement }; } case 'middleRows': { return { axis: 'y', container: this.middleColumn().nativeElement }; } } } static ɵfac = function CprWorkspaceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CprWorkspaceComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵdefineComponent"]({ type: CprWorkspaceComponent, selectors: [["lib-cpr-workspace"]], viewQuery: function CprWorkspaceComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵviewQuerySignal"](ctx.workspaceGrid, _c0, 5)(ctx.middleColumn, _c1, 5)(ctx.longAxisContainer, _c2, 5)(ctx.shortAxisContainer, _c3, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵqueryAdvance"](4); } }, hostAttrs: [1, "relative", "block", "h-full", "w-full"], hostVars: 6, hostBindings: function CprWorkspaceComponent_HostBindings(rf, ctx) { if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("--cpr-columns", ctx.columnTracks())("--cpr-middle-rows", ctx.middleRowTracks())("--cpr-rows", ctx.rowTracks()); } }, inputs: { axialTemplate: [1, "axialTemplate"], coronalTemplate: [1, "coronalTemplate"], reformatTemplate: [1, "reformatTemplate"], sagittalTemplate: [1, "sagittalTemplate"], cameraSliderTemplate: [1, "cameraSliderTemplate"], isBlur: [1, "isBlur"], isInitialViewportState: [1, "isInitialViewportState"], lastSelectedMPRViewport: [1, "lastSelectedMPRViewport"], selectedMPRViewport: [1, "selectedMPRViewport"] }, outputs: { resizeStart: "resizeStart", resizeEnd: "resizeEnd" }, decls: 40, vars: 52, consts: [["workspaceGrid", ""], ["cprLongAxisContainer", ""], ["middleColumn", ""], ["cprShortAxisContainer", ""], ["registeredPanel", ""], ["handle", ""], ["maximizeButton", ""], ["data-test-id", "cpr-div-workspace-header", 1, "pointer-events-auto", "absolute", "top-6", "left-6", "z-30", "flex", "items-center", "gap-1", "rounded", "bg-(--p-app-viewport-background)/60", "py-0.5", "pr-3", "pl-1", "text-(--p-app-viewport-label)"], ["data-test-id", "cpr-lib-viewport-button-exit-workspace", "icon", "arrow-left", "iconType", "prime", "tooltipPosition", "bottom", "tooltipStyleClass", "left-6! [&>.p-tooltip-arrow]:left-4!", 3, "click", "tooltip", "ariaLabel"], [1, "text-sm", "font-medium"], ["data-test-id", "cpr-div-panels", 1, "grid", "h-full", "w-full", "grid-cols-(--cpr-columns)", "grid-rows-(--cpr-rows)", "bg-(--p-app-viewport-background)"], ["data-viewport", "cpr-long-axis", 1, "relative", "overflow-hidden", "bg-(--p-app-viewport-background)", 3, "dblclick", "mousedown", "mousemove"], [1, "h-full", "w-full", 3, "ngClass"], [1, "relative", "h-full", "w-full"], [1, "h-full", "w-full", "bg-(--p-app-viewport-background)"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "grid", "grid-rows-(--cpr-middle-rows)", "bg-(--p-app-viewport-background)"], ["data-viewport", "cpr-short-axis", 1, "relative", "overflow-hidden", "bg-(--p-app-viewport-background)", 3, "dblclick", "mousedown", "mousemove"], ["alt", "", 1, "pointer-events-none", "absolute", "inset-0", "h-full", "w-full", 3, "src"], [1, "invisible", "absolute", "top-0", "left-0", "size-100", "overflow-hidden"], [4, "ngTemplateOutlet"], ["data-test-id", "cpr-lib-viewport-button-confirm-edit", "icon", "check", "iconType", "prime", "tooltipPosition", "bottom", 3, "click", "tooltip", "ariaLabel"], ["data-test-id", "cpr-lib-viewport-button-cancel-edit", "icon", "times", "iconType", "prime", "tooltipPosition", "bottom", 3, "click", "tooltip", "ariaLabel"], [1, "relative", "overflow-hidden", "bg-(--p-app-viewport-background)"], [3, "viewportName", "focusedViewport", "initialState", "lastFocused"], ["data-test-id", "cpr-div-camera-slider", 1, "pointer-events-none", "absolute", "top-0", "right-0", "z-10", "flex", "justify-end"], ["role", "separator", 1, "bg-surface-700", "hover:bg-primary-400", "touch-none", 3, "dragStarted", "dragMoved", "dragEnded", "libCprResizeHandle"], [1, "absolute", "right-0", "bottom-0", "z-10", "flex", "h-8", "items-center", "py-2", "pr-2"], ["iconType", "prime", "tooltipPosition", "top", 3, "click", "icon", "tooltip", "ariaLabel"]], template: function CprWorkspaceComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](0, "div", 7)(1, "lib-viewport-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("click", function CprWorkspaceComponent_Template_lib_viewport_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.exitWorkspace()); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](4, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](6, CprWorkspaceComponent_Conditional_6_Template, 6, 12); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](7, "div", 10, 0)(9, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("dblclick", function CprWorkspaceComponent_Template_div_dblclick_9_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.toggleMaximized("ribbon")); })("mousedown", function CprWorkspaceComponent_Template_div_mousedown_9_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.startWindowDrag($event)); })("mousemove", function CprWorkspaceComponent_Template_div_mousemove_9_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.updateWindowDrag($event, "ribbonA")); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](10, "div", 12)(11, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelement"](12, "div", 14, 1)(14, "lib-cpr-ribbon-overlay"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](15, CprWorkspaceComponent_ng_container_15_Template, 1, 0, "ng-container", 15); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](16, CprWorkspaceComponent_Conditional_16_Template, 1, 3, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](17, "div", 16, 2)(19, "div", 17); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵlistener"]("dblclick", function CprWorkspaceComponent_Template_div_dblclick_19_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.toggleMaximized("crossSection")); })("mousedown", function CprWorkspaceComponent_Template_div_mousedown_19_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.startWindowDrag($event)); })("mousemove", function CprWorkspaceComponent_Template_div_mousemove_19_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.updateWindowDrag($event, "crossSection")); }); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](20, "div", 12)(21, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelement"](22, "div", 14, 3); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](24, CprWorkspaceComponent_Conditional_24_Template, 1, 1, "img", 18); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelement"](25, "lib-cpr-cross-section-overlay"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](26, CprWorkspaceComponent_ng_container_26_Template, 1, 0, "ng-container", 15); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](27, CprWorkspaceComponent_Conditional_27_Template, 1, 3, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](28, CprWorkspaceComponent_ng_container_28_Template, 1, 0, "ng-container", 15); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditionalCreate"](29, CprWorkspaceComponent_Conditional_29_Template, 2, 6); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](30, CprWorkspaceComponent_ng_template_30_Template, 5, 19, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplateRefExtractor"])(32, CprWorkspaceComponent_ng_template_32_Template, 1, 13, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplateRefExtractor"])(34, CprWorkspaceComponent_ng_template_34_Template, 4, 8, "ng-template", null, 6, _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementStart"](36, "div", 19); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtemplate"](37, CprWorkspaceComponent_ng_container_37_Template, 1, 0, "ng-container", 20)(38, CprWorkspaceComponent_ng_container_38_Template, 1, 0, "ng-container", 20)(39, CprWorkspaceComponent_ng_container_39_Template, 1, 0, "ng-container", 20); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_25_0; const registeredPanel_r17 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵreference"](31); const maximizeButton_r18 = _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵreference"](35); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](2, 37, "planarReformation.exit"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpipeBind1"](3, 39, "planarReformation.exit")); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵtextInterpolate"](ctx.splineName()); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"](ctx.editing() ? 6 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("grid-area", ctx.panelArea("ribbon", "3 / 1 / 4 / -1"))("visibility", ctx.panelHidden("ribbon") ? "hidden" : null)("position", ctx.panelMaximized("ribbon") ? "absolute" : null)("inset", ctx.panelMaximized("ribbon") ? "0" : null); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction2"](41, _c4, ctx.isBlur(), !ctx.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", maximizeButton_r18)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](44, _c5)); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"](!ctx.horizontal() ? 16 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("display", ctx.horizontal() ? "contents" : null); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵstyleProp"]("grid-area", ctx.panelArea("crossSection", "1 / 1"))("visibility", ctx.panelHidden("crossSection") ? "hidden" : null)("position", ctx.panelMaximized("crossSection") ? "absolute" : null)("inset", ctx.panelMaximized("crossSection") ? "0" : null); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction2"](45, _c4, ctx.isBlur(), !ctx.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"]((tmp_25_0 = ctx.shortAxisFrozenFrame()) ? 24 : -1, tmp_25_0); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", maximizeButton_r18)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction0"](48, _c6)); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"](!ctx.horizontal() ? 27 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", registeredPanel_r17)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵpureFunction2"](49, _c7, ctx.reformatTemplate(), ctx.ViewportName.REFORMAT)); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵconditional"](ctx.horizontal() ? 29 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](8); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", ctx.axialTemplate()); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", ctx.sagittalTemplate()); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_17__["ɵɵproperty"]("ngTemplateOutlet", ctx.coronalTemplate()); } }, dependencies: [_cpr_cross_section_overlay_component__WEBPACK_IMPORTED_MODULE_12__.CprCrossSectionOverlayComponent, _cpr_resize_handle_directive__WEBPACK_IMPORTED_MODULE_13__.CprResizeHandleDirective, _cpr_ribbon_overlay_component__WEBPACK_IMPORTED_MODULE_14__.CprRibbonOverlayComponent, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgClass, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.ViewportButtonComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.ViewportIndicatorComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], styles: ["[_nghost-%COMP%] {\n --cpr-columns: minmax(0, 1.3fr) 4px minmax(0, 1fr);\n --cpr-rows: minmax(0, 1fr);\n --cpr-middle-rows: minmax(0, 1fr) 4px minmax(0, 1fr);\n}\n\n[role=separator][_ngcontent-%COMP%] {\n position: relative;\n}\n\n[role=separator][_ngcontent-%COMP%]::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n border-radius: var(--p-splitter-handle-border-radius);\n outline-color: transparent;\n}\n\n[role=separator][aria-orientation=vertical][_ngcontent-%COMP%]::after {\n height: 100%;\n width: 0.125rem;\n}\n\n[role=separator][aria-orientation=horizontal][_ngcontent-%COMP%]::after {\n height: 0.125rem;\n width: 100%;\n}\n\n[role=separator][_ngcontent-%COMP%]:focus-visible::after {\n box-shadow: var(--p-splitter-handle-focus-ring-shadow);\n outline: var(--p-splitter-handle-focus-ring-width) var(--p-splitter-handle-focus-ring-style) var(--p-splitter-handle-focus-ring-color);\n outline-offset: var(--p-splitter-handle-focus-ring-offset);\n}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL2xpYnMvZmVhdHVyZS9zcmMvbGliL3ZvbHVtZS12aWV3ZXIvY3ByL2Nwci13b3Jrc3BhY2UuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNJO0VBQ0Usa0RBQUE7RUFDQSwwQkFBQTtFQUNBLG9EQUFBO0FBQU47O0FBR0k7RUFDRSxrQkFBQTtBQUFOOztBQUdJO0VBQ0UsV0FBQTtFQUNBLGtCQUFBO0VBQ0EsUUFBQTtFQUNBLFNBQUE7RUFDQSxnQ0FBQTtFQUNBLHFEQUFBO0VBQ0EsMEJBQUE7QUFBTjs7QUFHSTtFQUNFLFlBQUE7RUFDQSxlQUFBO0FBQU47O0FBR0k7RUFDRSxnQkFBQTtFQUNBLFdBQUE7QUFBTjs7QUFHSTtFQUNFLHNEQUFBO0VBQ0Esc0lBQUE7RUFFQSwwREFBQTtBQUROIiwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgOmhvc3Qge1xuICAgICAgLS1jcHItY29sdW1uczogbWlubWF4KDAsIDEuM2ZyKSA0cHggbWlubWF4KDAsIDFmcik7XG4gICAgICAtLWNwci1yb3dzOiBtaW5tYXgoMCwgMWZyKTtcbiAgICAgIC0tY3ByLW1pZGRsZS1yb3dzOiBtaW5tYXgoMCwgMWZyKSA0cHggbWlubWF4KDAsIDFmcik7XG4gICAgfVxuXG4gICAgW3JvbGU9J3NlcGFyYXRvciddIHtcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICB9XG5cbiAgICBbcm9sZT0nc2VwYXJhdG9yJ106OmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6ICcnO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiA1MCU7XG4gICAgICBsZWZ0OiA1MCU7XG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWJvcmRlci1yYWRpdXMpO1xuICAgICAgb3V0bGluZS1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgfVxuXG4gICAgW3JvbGU9J3NlcGFyYXRvciddW2FyaWEtb3JpZW50YXRpb249J3ZlcnRpY2FsJ106OmFmdGVyIHtcbiAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgIHdpZHRoOiAwLjEyNXJlbTtcbiAgICB9XG5cbiAgICBbcm9sZT0nc2VwYXJhdG9yJ11bYXJpYS1vcmllbnRhdGlvbj0naG9yaXpvbnRhbCddOjphZnRlciB7XG4gICAgICBoZWlnaHQ6IDAuMTI1cmVtO1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgfVxuXG4gICAgW3JvbGU9J3NlcGFyYXRvciddOmZvY3VzLXZpc2libGU6OmFmdGVyIHtcbiAgICAgIGJveC1zaGFkb3c6IHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWZvY3VzLXJpbmctc2hhZG93KTtcbiAgICAgIG91dGxpbmU6IHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWZvY3VzLXJpbmctd2lkdGgpIHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWZvY3VzLXJpbmctc3R5bGUpXG4gICAgICAgIHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWZvY3VzLXJpbmctY29sb3IpO1xuICAgICAgb3V0bGluZS1vZmZzZXQ6IHZhcigtLXAtc3BsaXR0ZXItaGFuZGxlLWZvY3VzLXJpbmctb2Zmc2V0KTtcbiAgICB9XG4gICJdLCJzb3VyY2VSb290IjoiIn0= */"], changeDetection: 0 }); } /***/ }, /***/ 26144 /*!***************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cpr.service.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CprService: () => (/* binding */ CprService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _build_cpr_actor__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./build-cpr-actor */ 36896); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _cpr_image_data__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./cpr-image-data */ 3338); /* harmony import */ var _cpr_viewport__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./cpr-viewport */ 87660); /* harmony import */ var _cross_section_nodes__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./cross-section-nodes */ 54776); /* harmony import */ var _long_axis_camera__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./long-axis-camera */ 51984); /* harmony import */ var _short_axis_viewport__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./short-axis-viewport */ 9091); /* harmony import */ var _spline_to_centerline__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./spline-to-centerline */ 46815); /** * Drives CPR mode: flips the app into the `LayoutType.CPR` layout and, once its * viewports exist, renders the long-axis ribbon (owned `CprViewport`) and the * short-axis slice (a dedicated Cornerstone oblique-MPR viewport). Restores the * prior layout on exit. */ const LONG_AXIS_ACTOR_UID = 'cpr-long-axis'; class CprService { engine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_4__.RenderingEngineService); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.AnnotationFacade); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.viewportStore); session = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.cprSessionStore); renderSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_7__.renderSettingsStore); desiredLayout = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "desiredLayout" }] : [])); carrierContainers = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)({}, ...(ngDevMode ? [{ debugName: "carrierContainers" }] : [])); // The active phase's MPR volume id, set by the viewer. CPR reforms from this volume so it tracks // the active phase rather than whichever volume is first in the cache (multiphase series). activeVolumeId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "activeVolumeId" }] : [])); targetSpline = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "targetSpline" }] : [])); active = undefined; editSnapshot = undefined; pendingSnapWorld = undefined; // The fan-out runs again through the cursor effect, so this outlives the call that set it. recentreOnCursor = true; pendingSwitchRecentre = false; // Held for the drag: each move rebuilds the centerline, so the cursor must re-aim at the point. grabbedPointIndex = undefined; // The effect can refire during the async enable, before `active` is set. starting = false; hostsReady = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const containers = this.carrierContainers(); return this.desiredLayout() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.CPR && _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_REQUIRED_CARRIER_ROLES.every(role => !!containers[role]); }, ...(ngDevMode ? [{ debugName: "hostsReady" }] : [])); // Tracks the target spline's live data so CPR rebuilds on edit and cancels on delete. activeSplineData = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const id = this.targetSpline()?.id; return id ? this.annotationFacade.annotationMap()[id] : undefined; }, ...(ngDevMode ? [{ debugName: "activeSplineData" }] : [])); /** The spline being reformatted, for the drawer list's selection state. */ activeSplineId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.targetSpline()?.id, ...(ngDevMode ? [{ debugName: "activeSplineId" }] : [])); // Reads the live annotation, not the entry snapshot, so the bar follows renames. activeSplineName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.activeSplineData()?.name, ...(ngDevMode ? [{ debugName: "activeSplineName" }] : [])); // The framing the ribbon camera last applied — the SVG overlays' projection input. ribbonFraming = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "ribbonFraming" }] : [])); /** Closed splines wrap; the overlay ruler marks the seam at both ribbon ends. */ activeSplineIsClosed = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsClosedSpline)(this.activeSplineData()), ...(ngDevMode ? [{ debugName: "activeSplineIsClosed" }] : [])); activeSpline = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const annotation = this.activeSplineData(); return annotation && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(annotation) ? annotation : undefined; }, ...(ngDevMode ? [{ debugName: "activeSpline" }] : [])); controlPoints = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.activeSpline()?.points ?? [], ...(ngDevMode ? [{ debugName: "controlPoints" }] : [])); activeSplineColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.activeSpline()?.color, ...(ngDevMode ? [{ debugName: "activeSplineColor" }] : [])); // `updateCprCenterline` hands back a fresh object per rebuild, so derived state only // recomputes on that swap if the centerline is in the signal graph. centerline = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "centerline" }] : [])); centerlineLengthMm = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.centerline()?.totalLength ?? 0, ...(ngDevMode ? [{ debugName: "centerlineLengthMm" }] : [])); controlPointDistances = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const centerline = this.centerline(); return centerline ? (0,_cross_section_nodes__WEBPACK_IMPORTED_MODULE_14__.centerlineDistances)(centerline.positions, this.controlPoints()) : []; }, ...(ngDevMode ? [{ debugName: "controlPointDistances" }] : [])); // Bumped on every cross-section camera write: the engine is event-suppressed, so there is // no CAMERA_MODIFIED for the overlay to re-project its handles on. shortAxisCameraVersion = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "shortAxisCameraVersion" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const ready = this.hostsReady(); const spline = this.activeSplineData(); const wanted = this.targetSpline(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { if (!wanted) return; if (!spline || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(spline)) { this.cancel(); return; } if (!this.active) { if (ready && !this.starting) { this.startSession(spline).catch(() => { // startSession handles its own cleanup; empty catch satisfies no-floating-promises. }); } return; } this.rebuildForSpline(spline); }); }); // The carriers are orchestrator-unregistered, so the window effect never reaches the // ribbon actor; it reads the same store the MPR pipeline does instead. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const { level, width } = this.renderSettings.windowSettings(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.applyRibbonWindow(width, level)); }); // The store owns the cursor; every writer converges here to move the views. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const cursorMm = this.session.cursorMm(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.applyCursor(cursorMm)); }); // Zoom re-frames only the ribbon; the cross-section's FOV is fixed. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this.session.ribbonZoom(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.refreshLongAxisCamera()); }); // Rotation re-composes the cut plane's orientation array in place; the cameras // stay put — the image under them spins. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const rollRad = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.deg2rad)(this.session.rotationDeg()); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.applyRoll(rollRad)); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => this.tearDown()); } registerCarrierContainer(role, container) { this.carrierContainers.update(current => ({ ...current, [role]: container })); } unregisterCarrierContainer(role) { this.carrierContainers.update(current => { const next = { ...current }; delete next[role]; return next; }); } start(spline) { if (this.targetSpline()?.id === spline.id) return; this.cancelEdit(); this.releaseControlPoint(); // A switch re-frames the volume render; later edit rebuilds must not. this.pendingSwitchRecentre = true; this.session.setCursorMm(0); this.session.setRibbonZoom(1); this.session.setRotationDeg(0); this.session.setMaximizedPanel(undefined); this.targetSpline.set(spline); this.desiredLayout.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.CPR); } cancel() { this.cancelEdit(); this.targetSpline.set(undefined); this.tearDown(); } /** Edits are written straight to the annotation; this snapshot is what Cancel restores. */ beginEdit() { const spline = this.activeSplineData(); if (!spline || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(spline)) return; this.editSnapshot = { annotationId: spline.id, points: spline.points }; this.session.setEditState('editing'); } confirmEdit() { this.editSnapshot = undefined; this.session.setEditState('review'); } commitControlPointDrag(index, world) { const spline = this.activeSpline(); if (!spline) return; // Consumed by the rebuild this write triggers: the landing point's arc distance can only // be measured against the centerline the edit produces, never the one it replaces. this.pendingSnapWorld = world; this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_8__.movePoint)(spline, index, world)); } /** Restore the control points held at edit entry. Exit and spline switch both land here. */ cancelEdit() { const snapshot = this.editSnapshot; this.editSnapshot = undefined; this.session.setEditState('review'); if (!snapshot) return; // Keyed by the snapshot's own id: a spline deleted mid-edit leaves nothing to restore onto. const annotation = this.annotationFacade.annotationMap()[snapshot.annotationId]; if (!annotation || !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(annotation)) return; this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_8__.setPoints)(annotation, snapshot.points)); } // The engine's resize rescales parallelScale; re-assert the short-axis fixed FOV. refreshShortAxisCamera() { const active = this.active; if (!active) return; this.applyShortAxis(active.longAxis.bundle.centerline, this.session.cursorMm()); } shortAxisPlane() { return this.active?.shortAxis.handle?.plane(); } worldToCanvas(world) { return this.active?.shortAxis.handle?.worldToCanvas(world); } canvasToWorld(canvas) { return this.active?.shortAxis.handle?.canvasToWorld(canvas); } // resize(keepCamera) changes the carrier's aspect; re-fit the ribbon to the new box. refreshLongAxisCamera() { const longAxis = this.active?.longAxis; if (longAxis) this.applyLongAxisCamera(longAxis); } /** Nudge the cursor by a signed distance — wheel scrubs from either overlay land here. */ scrubCursor(deltaMm) { this.setCursor(this.session.cursorMm() + deltaMm); } /** The single clamp site: every cursor write lands inside the live arc. */ setCursor(distanceMm) { const active = this.active; if (!active) return; const total = active.longAxis.bundle.centerline.totalLength; this.recentreOnCursor = true; this.session.setCursorMm(Math.max(0, Math.min(total, distanceMm))); } /** A click on the active spline anywhere in the app: control point or bare centerline. */ snapCursorToSpline(details, viewportId, screenPos) { if (details.annotationId !== this.activeSplineId()) return; const centerline = this.active?.longAxis.bundle.centerline; if (!centerline) return; const { pointIndex } = details; if (pointIndex !== undefined) { this.grabbedPointIndex = pointIndex; const distanceMm = this.controlPointDistances()[pointIndex]; // The press may start a drag, which reads its target through the volume render's camera. if (distanceMm !== undefined) this.jumpCursor(distanceMm, false); return; } // Between control points there is no handle to read a position off, so intersect the // pick ray with the centerline instead. const ray = this.engine.getWorldRay(viewportId, screenPos); const hit = ray && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.closestPathPointToRay)(centerline.positions, ray); if (hit) this.jumpCursor((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.calculateDistanceOnPath)(centerline.positions, hit), false); } releaseControlPoint() { this.grabbedPointIndex = undefined; } /** * A click straight onto a control point. A scrub converges over many writes and a single * write cannot, so the fan-out and the repaint both run unconditionally here. */ jumpCursor(distanceMm, recentre = true) { const active = this.active; if (!active) return; const centerline = active.longAxis.bundle.centerline; const cursorMm = Math.max(0, Math.min(distanceMm, centerline.totalLength)); // Re-aiming and repainting an unmoved cursor would shift a view that has settled. if (cursorMm === this.session.cursorMm()) return; this.recentreOnCursor = recentre; this.session.setCursorMm(cursorMm); this.applyCursor(cursorMm); this.repaintShortAxis(centerline, cursorMm); } /** * Frame the ribbon: the whole reformation at zoom 1, else zoomed about the cursor. * Reads the session store, so scroll, zoom and resize all land here. */ applyLongAxisCamera(state) { const camera = state.viewport.camera; const focal = camera.getFocalPoint(); const orientation = this.session.orientation(); const ribbonLengthMm = state.bundle.centerline.totalLength; const framing = (0,_long_axis_camera__WEBPACK_IMPORTED_MODULE_15__.frameLongAxis)({ aspect: longAxisAspect(state.host), cursorMm: this.session.cursorMm(), orientation, previousFocal: state.framed ? { x: focal[0] ?? 0, y: focal[1] ?? 0 } : undefined, ribbonLengthMm, ribbonWidthMm: _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_WIDTH_MM, zoom: this.session.ribbonZoom() }); camera.setParallelProjection(true); camera.setParallelScale(framing.parallelScale); camera.setFocalPoint(framing.focalX, framing.focalY, 0); camera.setPosition(framing.focalX, framing.focalY, _cpr_config__WEBPACK_IMPORTED_MODULE_11__.LONG_AXIS_CAMERA_DISTANCE_MM); camera.setViewUp(...framing.viewUp); camera.setClippingRange(_cpr_config__WEBPACK_IMPORTED_MODULE_11__.LONG_AXIS_CAMERA_DISTANCE_MM * 0.5, _cpr_config__WEBPACK_IMPORTED_MODULE_11__.LONG_AXIS_CAMERA_DISTANCE_MM * 1.5); state.framed = true; state.viewport.requestRender(); this.ribbonFraming.set({ focalX: framing.focalX, focalY: framing.focalY, orientation, parallelScale: framing.parallelScale, ribbonLengthMm, ribbonWidthMm: _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_WIDTH_MM }); } applyRibbonWindow(width, level) { const longAxis = this.active?.longAxis; if (!longAxis) return; const property = longAxis.bundle.actor.getProperty(); property.setColorWindow(width); property.setColorLevel(level); longAxis.viewport.requestRender(); } startSession(spline) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this.starting = true; try { const containers = _this.carrierContainers(); const ribbonContainer = containers.ribbonA; const crossSectionContainer = containers.crossSection; const binding = _this.resolvePrimaryVolume(); if (!ribbonContainer || !crossSectionContainer || !binding) return; const cprImageData = (0,_cpr_image_data__WEBPACK_IMPORTED_MODULE_12__.buildCprImageData)(binding.imageData); let host; try { yield _this.engine.enable(ribbonContainer, { id: _cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS.ribbonA, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportType.ORTHOGRAPHIC, volumeId: binding.volumeId }); host = _this.getHost(_cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS.ribbonA); } catch { host = undefined; } // Bail if the enable failed or the session was cancelled/re-targeted mid-await. if (!host || _this.targetSpline()?.id !== spline.id || _this.desiredLayout() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.CPR) { _this.engine.disable(_cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS.ribbonA); return; } const longAxis = _this.startLongAxis(host, cprImageData, spline); const shortAxis = { handle: undefined }; _this.active = { enabledRoles: new Set(['ribbonA']), longAxis, shortAxis }; _this.startShortAxis(binding, longAxis, shortAxis, crossSectionContainer); // Initial setup already placed the crosshair with recentering enabled. _this.pendingSwitchRecentre = false; } finally { _this.starting = false; } })(); } startLongAxis(host, imageData, spline) { const viewport = new _cpr_viewport__WEBPACK_IMPORTED_MODULE_13__.CprViewport(host, 'long-axis'); const bundle = (0,_build_cpr_actor__WEBPACK_IMPORTED_MODULE_10__.buildCprActor)(imageData, spline, this.currentRollRad()); viewport.setActors([{ actor: bundle.actor, uid: LONG_AXIS_ACTOR_UID }]); const state = { bundle, framed: false, host, imageData, viewport }; this.centerline.set(bundle.centerline); this.applyLongAxisCamera(state); return state; } startShortAxis(binding, longAxis, shortAxis, container) { const centerline = longAxis.bundle.centerline; const initial = centerline.totalLength * _cpr_config__WEBPACK_IMPORTED_MODULE_11__.SHORT_AXIS_INITIAL_POSITION_FRACTION; this.session.setCursorMm(initial); this.pushCrosshair(centerline, initial, true); (0,_short_axis_viewport__WEBPACK_IMPORTED_MODULE_16__.startShortAxisViewport)({ centerline, container, engine: this.engine, initialDistance: initial, volumeId: binding.volumeId }).then(handle => { if (this.active?.shortAxis !== shortAxis) { this.engine.disable(_cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS.crossSection); return; } shortAxis.handle = handle; this.active.enabledRoles.add('crossSection'); // Both carriers enable after the last window write, so take the current settings now: // the ribbon through its actor, the cross-section through the engine's VOI pass. const { level, width } = this.renderSettings.windowSettings(); this.applyRibbonWindow(width, level); this.engine.updateMPRWindow(width, level); // Enabling a viewport re-tiles the shared offscreen surface, so both carriers' // fixed-FOV cameras have to be re-asserted once the last one is up. this.refreshShortAxisCamera(); this.refreshLongAxisCamera(); this.forceShortAxisRepaint(); }).catch(() => { // Enable failed; the long-axis still renders and teardown stays safe. }); } /** * Re-applying the corrected entry camera leaves the MTime unchanged, so without this the * short-axis keeps Cornerstone's volume-load reset (axial, fit-to-volume) until the first * scroll. Deferred so the entry churn settles first. */ forceShortAxisRepaint() { const nudge = () => { const active = this.active; if (!active?.shortAxis.handle) return; this.repaintShortAxis(active.longAxis.bundle.centerline, this.session.cursorMm()); }; const idle = globalThis.requestIdleCallback; if (idle) idle(nudge, { timeout: 2000 });else setTimeout(nudge, 500); } // A still-active session over a changed spline: keep the cursor where the user had it, // clamped to the edited length. Switches via start() open at 0 — it resets the store first. rebuildForSpline(spline) { if (!this.active) return; const centerline = (0,_build_cpr_actor__WEBPACK_IMPORTED_MODULE_10__.updateCprCenterline)(this.active.longAxis.bundle, spline, this.currentRollRad()); this.centerline.set(centerline); // The grabbed point has just moved, so it wins over the cursor's old arc distance. const grabbed = this.grabbedPointIndex; const snapWorld = this.pendingSnapWorld ?? (grabbed === undefined ? undefined : this.controlPoints()[grabbed]); this.pendingSnapWorld = undefined; const target = snapWorld ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.calculateDistanceOnPath)(centerline.positions, snapWorld) : this.session.cursorMm(); const cursorMm = Math.max(0, Math.min(target, centerline.totalLength)); // An edit moves the geometry under a held cursor, so only a switch re-frames. this.recentreOnCursor = this.pendingSwitchRecentre; this.pendingSwitchRecentre = false; this.session.setCursorMm(cursorMm); // The setter no-ops on an unchanged value, so the fan-out to the rebuilt // centerline has to run unconditionally. this.applyCursor(cursorMm); // The engine may skip the render above. A scrub repaints on its next tick; a rebuild cannot. this.repaintShortAxis(centerline, cursorMm); } applyCursor(cursorMm) { const active = this.active; if (!active) return; const centerline = active.longAxis.bundle.centerline; this.applyShortAxis(centerline, cursorMm); this.pushCrosshair(centerline, cursorMm, this.recentreOnCursor); this.applyLongAxisCamera(active.longAxis); } // Change the slice and restore it in one tick: only the final frame paints, but the MTime // advances, so the engine cannot skip the GPU render and the on-screen copy. repaintShortAxis(centerline, cursorMm) { const deltaMm = cursorMm + 1 <= centerline.totalLength ? 1 : -1; this.applyShortAxis(centerline, cursorMm + deltaMm); this.applyShortAxis(centerline, cursorMm); } // The one place the cross-section camera moves, so the overlay has one thing to watch. applyShortAxis(centerline, distanceMm) { const handle = this.active?.shortAxis.handle; if (!handle) return; handle.apply(centerline, distanceMm); this.shortAxisCameraVersion.update(version => version + 1); } applyRoll(rollRad) { const active = this.active; if (!active) return; (0,_spline_to_centerline__WEBPACK_IMPORTED_MODULE_17__.applyCenterlineRoll)(active.longAxis.bundle.centerline, rollRad); active.longAxis.viewport.requestRender(); } currentRollRad() { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.deg2rad)(this.session.rotationDeg()); } tearDown() { if (!this.active) return; const { enabledRoles, longAxis } = this.active; this.active = undefined; // Dispose the owned renderer before disabling the carrier it rides on. The mapper // and its private inputs go too, or their GL textures outlive the session. longAxis.viewport.dispose(); deleteVtkObject(longAxis.bundle.actor); deleteVtkObject(longAxis.bundle.mapper); deleteVtkObject(longAxis.bundle.centerline.polyData); deleteVtkObject(longAxis.imageData); for (const role of enabledRoles) this.engine.disable(_cpr_config__WEBPACK_IMPORTED_MODULE_11__.CPR_CARRIER_VIEWPORT_IDS[role]); this.centerline.set(undefined); // A commit whose rebuild never arrived must not snap the next session's cursor. this.pendingSnapWorld = undefined; this.releaseControlPoint(); this.ribbonFraming.set(undefined); this.desiredLayout.set(undefined); } pushCrosshair(centerline, distance, recentre) { const sample = (0,_spline_to_centerline__WEBPACK_IMPORTED_MODULE_17__.sampleCenterlineAt)(centerline, distance); if (!sample) return; const position = [sample.position[0], sample.position[1], sample.position[2]]; // Pan first: `updateIntersection` separates the two, so the isocenter must already be set. if (recentre) this.viewportStore.updateIsoCenter(position); this.viewportStore.updateIntersection(position); } getHost(viewportId) { return this.engine.getViewport(viewportId); } resolvePrimaryVolume() { const activeId = this.activeVolumeId(); const volume = activeId ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(activeId) : (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.getPrimaryImageVolume)(); if (!volume?.imageData) return undefined; return { imageData: volume.imageData, volumeId: volume.volumeId }; } static ɵfac = function CprService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CprService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: CprService, factory: CprService.ɵfac }); } function longAxisAspect(host) { const width = host.canvas?.width ?? 1; const height = host.canvas?.height ?? 1; return height > 0 ? width / height : 1; } // `.delete()` is the vtk runtime method but isn't always on the typed surface. function deleteVtkObject(object) { object?.delete?.(); } /***/ }, /***/ 3832 /*!**************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cross-section-cut-line.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cutLineGeometry: () => (/* binding */ cutLineGeometry), /* harmony export */ pointerAngleDeg: () => (/* binding */ pointerAngleDeg) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cpr-config */ 17924); /** * The cross-section's cut-line indicator: where the ribbon's rotated plane cuts * this slice. The short-axis camera is framed from the same centerline frame the * roll composes onto — screen-right is the zero-roll lateral, screen-up the * frame's up — so the on-screen angle IS the roll, no world math needed. */ function cutLineGeometry(box, rotationDeg) { const centerX = box.width / 2; const centerY = box.height / 2; const rollRad = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.deg2rad)(rotationDeg); // Screen y runs down, so a positive roll turns the line counter-clockwise. const dx = Math.cos(rollRad); const dy = -Math.sin(rollRad); // The camera shows SHORT_AXIS_FOV_MM over the box height; reach past the corners. const gapHalf = _cpr_config__WEBPACK_IMPORTED_MODULE_1__.CURSOR_GAP_MM / 2 * (box.height / _cpr_config__WEBPACK_IMPORTED_MODULE_1__.SHORT_AXIS_FOV_MM); const reach = Math.hypot(box.width, box.height) / 2; const segment = (from, to) => ({ x1: centerX + dx * from, x2: centerX + dx * to, y1: centerY + dy * from, y2: centerY + dy * to }); return { gapFill: segment(-gapHalf, gapHalf), segments: [segment(-reach, -gapHalf), segment(gapHalf, reach)] }; } /** The pointer's angle about the view centre, in the cut-line's degree convention. */ function pointerAngleDeg(box, x, y) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.rad2deg)(Math.atan2(box.height / 2 - y, x - box.width / 2)); } /***/ }, /***/ 54776 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/cross-section-nodes.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ centerlineDistances: () => (/* binding */ centerlineDistances), /* harmony export */ inPlaneDragTarget: () => (/* binding */ inPlaneDragTarget), /* harmony export */ nearPlaneNodeIndices: () => (/* binding */ nearPlaneNodeIndices), /* harmony export */ planeOffsetMm: () => (/* binding */ planeOffsetMm) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Pure geometry behind the cross-section's control-point handles: which points are near * enough to the slice to show, where a dragged one lands, and where each sits along the arc. */ /** Signed distance from the slice plane along its normal, in millimetres. */ function planeOffsetMm(point, focalPoint, normal) { const offset = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), point, focalPoint); return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(offset, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), normal)); } /** The control points that get a handle: an off-plane one would drag with invisible depth error. */ function nearPlaneNodeIndices(input) { const { focalPoint, grabbedIndex, normal, points, toleranceMm } = input; const indices = []; for (const [index, point] of points.entries()) { const near = Math.abs(planeOffsetMm(point, focalPoint, normal)) < toleranceMm; if (near || index === grabbedIndex) indices.push(index); } return indices; } /** * Where a dragged control point lands: the pointer's position on the view plane, pushed back * out to the depth the point already had — a drag must never move a point through the slice. */ function inPlaneDragTarget(input) { const { nodePosition, normal, onPlane } = input; const unitNormal = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), normal); const depth = planeOffsetMm(nodePosition, onPlane, normal); return [onPlane[0] + unitNormal[0] * depth, onPlane[1] + unitNormal[1] * depth, onPlane[2] + unitNormal[2] * depth]; } /** * Arc distance of each control point. Always pass `CenterlineData.positions`, never * `getSplinePath(spline)`: the sampler reverses a bottom-up path, so spline-path distance * can run backwards against `cursorMm`. */ function centerlineDistances(positions, points) { return points.map(point => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.calculateDistanceOnPath)(positions, point)); } /***/ }, /***/ 87242 /*!******************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/grid-fractions.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MIN_TRACK_SHARE: () => (/* binding */ MIN_TRACK_SHARE), /* harmony export */ WORKSPACE_GUTTER_PX: () => (/* binding */ WORKSPACE_GUTTER_PX), /* harmony export */ availableTrackPx: () => (/* binding */ availableTrackPx), /* harmony export */ resizeTracks: () => (/* binding */ resizeTracks), /* harmony export */ trackList: () => (/* binding */ trackList), /* harmony export */ trackSharePercent: () => (/* binding */ trackSharePercent) /* harmony export */ }); /** Grid track fractions for the CPR workspace and the drag math that keeps them valid. */ /** Gutter between workspace panels, in px — the `p-splitter` gutter size the grid replaced. */ const WORKSPACE_GUTTER_PX = 4; /** Smallest share of a track list one panel may keep; parity with the old `p-splitter` `minSizes: 5`. */ const MIN_TRACK_SHARE = 0.05; /** A `grid-template-*` value: fraction tracks separated by fixed gutter tracks for the drag handles. */ function trackList(fractions) { return fractions.map(fraction => `minmax(0,${fraction}fr)`).join(` ${WORKSPACE_GUTTER_PX}px `); } /** The px the fraction tracks share, i.e. the container minus its gutter tracks. */ function availableTrackPx(containerPx, trackCount) { return Math.max(0, containerPx - Math.max(0, trackCount - 1) * WORKSPACE_GUTTER_PX); } /** The share of the whole track list held before the boundary, in percent — for ARIA. */ function trackSharePercent(fractions, boundary) { const total = fractions.reduce((sum, fraction) => sum + fraction, 0); let before = 0; for (let index = 0; index <= boundary; index++) before += fractions[index] ?? 0; return total > 0 ? Math.round(100 * before / total) : 50; } /** * Move `deltaPx` across the boundary between tracks `boundary` and `boundary + 1`, as * `p-splitter` did: only the two adjacent tracks trade, neither drops below * `MIN_TRACK_SHARE`, and the fraction total is preserved. */ function resizeTracks(fractions, boundary, deltaPx, availablePx) { const next = [...fractions]; const before = fractions[boundary]; const after = fractions[boundary + 1]; const total = fractions.reduce((sum, fraction) => sum + fraction, 0); if (before === undefined || after === undefined || total <= 0 || availablePx <= 0) return next; if (deltaPx === 0) return next; const pairFraction = before + after; const pairPx = availablePx * (pairFraction / total); const minPx = availablePx * MIN_TRACK_SHARE; if (pairPx < minPx * 2) return next; const startPx = availablePx * (before / total); const movedPx = Math.min(Math.max(startPx + deltaPx, minPx), pairPx - minPx); next[boundary] = pairFraction * (movedPx / pairPx); next[boundary + 1] = pairFraction - next[boundary]; return next; } /***/ }, /***/ 51984 /*!********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/long-axis-camera.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MAX_RIBBON_ZOOM: () => (/* binding */ MAX_RIBBON_ZOOM), /* harmony export */ clampRibbonZoom: () => (/* binding */ clampRibbonZoom), /* harmony export */ fitParallelScale: () => (/* binding */ fitParallelScale), /* harmony export */ followAxis: () => (/* binding */ followAxis), /* harmony export */ frameLongAxis: () => (/* binding */ frameLongAxis) /* harmony export */ }); /* harmony import */ var _ribbon_projection__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ribbon-projection */ 94212); const MAX_RIBBON_ZOOM = 8; function clampRibbonZoom(zoom) { if (!Number.isFinite(zoom)) return 1; return Math.min(MAX_RIBBON_ZOOM, Math.max(1, zoom)); } /** * Half-height that fits the whole ribbon, with a 2% margin: the larger of what the * arc length needs and what the radial width needs, given which axis each occupies on screen. */ function fitParallelScale(input) { const aspect = input.aspect > 0 ? input.aspect : 1; const halfWidth = input.ribbonWidthMm / 2; const fit = input.orientation === 'vertical' ? Math.max(input.ribbonLengthMm / 2, halfWidth / aspect) : Math.max(halfWidth, input.ribbonLengthMm / (2 * aspect)); return fit * 1.02; } function frameLongAxis(input) { const aspect = input.aspect > 0 ? input.aspect : 1; const vertical = input.orientation === 'vertical'; const halfWidth = input.ribbonWidthMm / 2; const parallelScale = fitParallelScale(input) / clampRibbonZoom(input.zoom); // parallelScale is always the on-screen vertical half-extent; which ribbon axis that // covers depends on the roll. const alongHalf = vertical ? parallelScale : parallelScale * aspect; const acrossHalf = vertical ? parallelScale * aspect : parallelScale; return { focalX: followAxis(input.previousFocal?.x, halfWidth, acrossHalf, input.ribbonWidthMm), focalY: followAxis(input.previousFocal?.y, (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_0__.arcToWorldY)(input.ribbonLengthMm, input.cursorMm), alongHalf, input.ribbonLengthMm), parallelScale, // Rolling viewUp onto -x puts arc length across the screen, distal left to proximal right. viewUp: vertical ? [0, 1, 0] : [-1, 0, 0] }; } /** * Keep `target` in view along one axis: centred while everything fits, otherwise held * inside a dead-zone so the view only scrolls once the cursor nears an edge. */ function followAxis(previous, target, halfExtent, length) { if (halfExtent >= length / 2) return length / 2; const clamp = value => Math.min(Math.max(value, halfExtent), length - halfExtent); const focal = clamp(previous ?? target); const deadZoneHalf = 0.6 * halfExtent; const offset = target - focal; if (Math.abs(offset) <= deadZoneHalf) return clamp(focal); return clamp(target - Math.sign(offset) * deadZoneHalf); } /***/ }, /***/ 36955 /*!*****************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/ribbon-cursor.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cursorCrossBar: () => (/* binding */ cursorCrossBar) /* harmony export */ }); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _ribbon_projection__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ribbon-projection */ 94212); /** * The cursor cross-bar's canvas geometry: a line perpendicular to the arc at the * cursor, split around a central gap so the anatomy stays visible; the gap itself * carries a faint fill so the line reads as one. */ function cursorCrossBar(framing, box, cursorMm) { const half = framing.ribbonWidthMm / 2; const gapHalf = Math.min(_cpr_config__WEBPACK_IMPORTED_MODULE_0__.CURSOR_GAP_MM / 2, half); const segment = (from, to) => { const [x1, y1] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_1__.ribbonToCanvas)(framing, box, { d: cursorMm, lambda: from }); const [x2, y2] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_1__.ribbonToCanvas)(framing, box, { d: cursorMm, lambda: to }); return { x1, x2, y1, y2 }; }; return { gapFill: segment(-gapHalf, gapHalf), segments: [segment(-half, -gapHalf), segment(gapHalf, half)] }; } /***/ }, /***/ 61193 /*!*******************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/ribbon-gestures.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STILL_CLICK_MAX_PX: () => (/* binding */ STILL_CLICK_MAX_PX), /* harmony export */ exceedsStillClick: () => (/* binding */ exceedsStillClick), /* harmony export */ normalizeWheelDeltaY: () => (/* binding */ normalizeWheelDeltaY), /* harmony export */ releaseCapturedPointer: () => (/* binding */ releaseCapturedPointer), /* harmony export */ wheelCursorStepMm: () => (/* binding */ wheelCursorStepMm) /* harmony export */ }); /** * Gesture math for the ribbon overlay: the plain-wheel cursor step and the * still-click discriminator (a press that never strays past the threshold jumps * the cursor; one that does becomes a rotation drag). */ /** Movement beyond this is a drag; at or under it, releasing counts as a click. */ const STILL_CLICK_MAX_PX = 3; /** What a line/page-mode notch reads as, in px — the classic mouse pixel delta. */ const NOTCH_EQUIVALENT_PX = 100; /** The step math assumes pixel deltas; line/page modes deliver ~±3 per notch. */ function normalizeWheelDeltaY(deltaY, deltaMode) { return deltaMode === WheelEvent.DOM_DELTA_PIXEL ? deltaY : Math.sign(deltaY) * NOTCH_EQUIVALENT_PX; } const WHEEL_DELTA_CAP = 50; const WHEEL_STEP_MM_PER_DELTAY = 0.02; const WHEEL_SHIFT_MULTIPLIER = 5; /** * Plain-wheel cursor nudge: ~1 mm per mouse notch, capped per event so a fast * wheel cannot jump, shift for coarse steps. Wheel down advances the cursor distally. */ function wheelCursorStepMm(deltaY, shiftKey) { const capped = Math.max(-WHEEL_DELTA_CAP, Math.min(WHEEL_DELTA_CAP, deltaY)); return capped * WHEEL_STEP_MM_PER_DELTAY * (shiftKey ? WHEEL_SHIFT_MULTIPLIER : 1); } function exceedsStillClick(startX, startY, x, y) { return Math.hypot(x - startX, y - startY) > STILL_CLICK_MAX_PX; } /** Release only a capture the target actually holds; a bare release can throw. */ function releaseCapturedPointer(event) { const target = event.target; if (target.hasPointerCapture?.(event.pointerId)) target.releasePointerCapture(event.pointerId); } /***/ }, /***/ 94212 /*!*********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/ribbon-projection.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ arcToWorldY: () => (/* binding */ arcToWorldY), /* harmony export */ canvasToRibbon: () => (/* binding */ canvasToRibbon), /* harmony export */ pxPerMm: () => (/* binding */ pxPerMm), /* harmony export */ ribbonToCanvas: () => (/* binding */ ribbonToCanvas) /* harmony export */ }); /** * CSS pixels per ribbon millimetre. parallelScale is the on-screen vertical * half-extent in mm, whichever orientation is showing. */ function pxPerMm(framing, box) { const height = box.height > 0 ? box.height : 1; const parallelScale = framing.parallelScale > 0 ? framing.parallelScale : 1; return height / (2 * parallelScale); } /** * Arc length ↔ the mapper's world y: it stacks its quads at `totalHeight - distance`, so * d = 0 sits at ribbonLengthMm and the arc descends. Self-inverse. */ function arcToWorldY(ribbonLengthMm, d) { return ribbonLengthMm - d; } function ribbonToCanvas(framing, box, point) { const scale = pxPerMm(framing, box); const x = framing.ribbonWidthMm / 2 + point.lambda - framing.focalX; const y = arcToWorldY(framing.ribbonLengthMm, point.d) - framing.focalY; // Screen axes follow the camera roll: vertical is viewUp +y (arc up the screen), // horizontal rolls viewUp onto -x (arc across the screen, lateral down it). if (framing.orientation === 'vertical') { return [box.width / 2 + x * scale, box.height / 2 - y * scale]; } return [box.width / 2 + y * scale, box.height / 2 + x * scale]; } function canvasToRibbon(framing, box, xPx, yPx) { const scale = pxPerMm(framing, box); const vertical = framing.orientation === 'vertical'; const x = (vertical ? xPx - box.width / 2 : yPx - box.height / 2) / scale; const y = (vertical ? box.height / 2 - yPx : xPx - box.width / 2) / scale; return { d: arcToWorldY(framing.ribbonLengthMm, framing.focalY + y), lambda: framing.focalX + x - framing.ribbonWidthMm / 2 }; } /***/ }, /***/ 15701 /*!****************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/ribbon-ruler.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectRulerTick: () => (/* binding */ projectRulerTick), /* harmony export */ rulerTicks: () => (/* binding */ rulerTicks) /* harmony export */ }); /* harmony import */ var _ribbon_projection__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ribbon-projection */ 94212); /** * Arc-length ruler for the ribbon overlay: tick generation and placement at the * ruler edge — minor ticks every 10 mm, labeled majors every 50 mm, seam ticks * marking a closed spline's wrap point at both ribbon ends. */ const MINOR_SPACING_MM = 10; const MAJOR_SPACING_MM = 50; const MINOR_INSET_PX = 5; const MAJOR_INSET_PX = 10; const SEAM_INSET_PX = 14; const LABEL_INSET_PX = 14; const LABEL_BASELINE_OFFSET_PX = 3; function rulerTicks(lengthMm, closed) { const ticks = []; for (let d = 0; d <= lengthMm; d += MINOR_SPACING_MM) { const major = d % MAJOR_SPACING_MM === 0; ticks.push({ d, label: major ? `${d}` : undefined, major, seam: false }); } if (closed) { ticks.push({ d: 0, label: undefined, major: true, seam: true }, { d: lengthMm, label: undefined, major: true, seam: true }); } return ticks; } function tickInsetPx(tick) { if (tick.seam) return SEAM_INSET_PX; return tick.major ? MAJOR_INSET_PX : MINOR_INSET_PX; } /** Place a tick at the ruler edge, inset into the ribbon across the arc's axis. */ function projectRulerTick(framing, box, tick) { const [x, y] = (0,_ribbon_projection__WEBPACK_IMPORTED_MODULE_0__.ribbonToCanvas)(framing, box, { d: tick.d, lambda: -framing.ribbonWidthMm / 2 }); const inset = tickInsetPx(tick); const vertical = framing.orientation === 'vertical'; return { ...tick, labelX: vertical ? x + LABEL_INSET_PX : x, labelY: (vertical ? y : y + LABEL_INSET_PX) + LABEL_BASELINE_OFFSET_PX, x1: x, x2: vertical ? x + inset : x, y1: y, y2: vertical ? y : y + inset }; } /***/ }, /***/ 9091 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/short-axis-viewport.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ startShortAxisViewport: () => (/* binding */ startShortAxisViewport) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _cpr_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./cpr-config */ 17924); /* harmony import */ var _spline_to_centerline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spline-to-centerline */ 46815); function toPoint3(values) { return [values[0] ?? 0, values[1] ?? 0, values[2] ?? 0]; } function startShortAxisViewport(_x) { return _startShortAxisViewport.apply(this, arguments); } function _startShortAxisViewport() { _startShortAxisViewport = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (arguments_) { const { container, engine, volumeId } = arguments_; yield engine.enable(container, { id: _cpr_config__WEBPACK_IMPORTED_MODULE_3__.CPR_CARRIER_VIEWPORT_IDS.crossSection, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportType.ORTHOGRAPHIC, volumeId }); const viewport = engine.getViewport(_cpr_config__WEBPACK_IMPORTED_MODULE_3__.CPR_CARRIER_VIEWPORT_IDS.crossSection); function apply(centerline, distance) { const sample = (0,_spline_to_centerline__WEBPACK_IMPORTED_MODULE_4__.sampleCenterlineAt)(centerline, distance); if (!sample || !viewport) return; const focalPoint = toPoint3(sample.position); const normal = toPoint3(sample.tangent); // vtk derives viewPlaneNormal from (position − focalPoint), so set position // explicitly along the tangent — setting focalPoint alone keeps the stale // position and flips the normal when the focal point scrolls past it. const current = viewport.getCamera?.(); const camDistribution = current?.position && current?.focalPoint ? gl_matrix__WEBPACK_IMPORTED_MODULE_1__.distance(current.position, current.focalPoint) || _cpr_config__WEBPACK_IMPORTED_MODULE_3__.SHORT_AXIS_FOV_MM * 2 : _cpr_config__WEBPACK_IMPORTED_MODULE_3__.SHORT_AXIS_FOV_MM * 2; const cameraPosition = [focalPoint[0] + normal[0] * camDistribution, focalPoint[1] + normal[1] * camDistribution, focalPoint[2] + normal[2] * camDistribution]; viewport.setCamera({ focalPoint, parallelScale: _cpr_config__WEBPACK_IMPORTED_MODULE_3__.SHORT_AXIS_FOV_MM / 2, position: cameraPosition, viewUp: toPoint3(sample.viewUp) }); viewport.render(); } function plane() { const camera = viewport?.getCamera(); if (!camera?.focalPoint || !camera?.viewPlaneNormal) return undefined; return { focalPoint: toPoint3(camera.focalPoint), normal: toPoint3(camera.viewPlaneNormal) }; } function worldToCanvas(world) { const canvas = viewport?.worldToCanvas(toPoint3(world)); return canvas ? [canvas[0], canvas[1]] : undefined; } function canvasToWorld(canvas) { const world = viewport?.canvasToWorld(canvas); return world ? toPoint3(world) : undefined; } apply(arguments_.centerline, arguments_.initialDistance); // Wheel scrubbing lives on the cross-section overlay; disabling the carrier // viewport is `CprService`'s job — it owns the role registry. return { apply, canvasToWorld, plane, worldToCanvas }; }); return _startShortAxisViewport.apply(this, arguments); } /***/ }, /***/ 46815 /*!************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/cpr/spline-to-centerline.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CPR_ORIENTATION_ARRAY_NAME: () => (/* binding */ CPR_ORIENTATION_ARRAY_NAME), /* harmony export */ applyCenterlineRoll: () => (/* binding */ applyCenterlineRoll), /* harmony export */ frameWithRoll: () => (/* binding */ frameWithRoll), /* harmony export */ pickUpAxis: () => (/* binding */ pickUpAxis), /* harmony export */ sampleCenterlineAt: () => (/* binding */ sampleCenterlineAt), /* harmony export */ splineToCenterline: () => (/* binding */ splineToCenterline) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/Core/DataArray */ 40928); /* harmony import */ var _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/PolyData */ 95765); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 85648); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /** * Convert a Spline into the inputs `vtkImageCPRMapper` needs: a `vtkPolyData` * centerline with a per-point quaternion `Orientation` PointData array, a * cumulative arc-length lookup, and the per-point orientation frames. * * Frames are parallel-transported (rotation-minimizing) along the path — seeded * from a world-axis projection at the first point, then propagated by the minimal * rotation between consecutive tangents — so the user's roll (composed about the * local tangent into the orientation array) sweeps no seams on tortuous curves. * Frame convention: columns [lateral | up | tangent], i.e. local Z is the tangent * and local X is the mapper's sampling direction. */ const CPR_ORIENTATION_ARRAY_NAME = 'Orientation'; function splineToCenterline(spline, rollRad = 0) { const positions = orientPositionsForCpr((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getSplinePath)(spline)); const polyData = buildCenterlinePolyData(positions); const { cumulativeDistances, totalLength } = buildCumulativeDistances(positions); const frames = buildParallelTransportFrames(positions); distributeClosedPathTwist(positions, frames, cumulativeDistances, totalLength); writeOrientationArray(polyData, frames, rollRad); return { cumulativeDistances, frames, polyData, positions, totalLength }; } /** Re-compose the Orientation array for a new roll, in place on the live polydata. */ function applyCenterlineRoll(centerline, rollRad) { writeOrientationArray(centerline.polyData, centerline.frames, rollRad); } /** Compose a roll about the local tangent (local Z) onto a frame quaternion. */ function frameWithRoll(out, frame, rollRad) { const roll = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), [0, 0, 1], rollRad); return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.multiply(out, frame, roll); } // The mapper draws d = 0 at the top of the ribbon, where the proximal end belongs. For these // vessels that is the superior end, so keep the greater Z first however the spline was drawn. function orientPositionsForCpr(path) { const first = path[0]; const last = path.at(-1); if (first && last && path.length >= 2 && first[2] < last[2]) { return path.toReversed(); } return [...path]; } function buildCenterlinePolyData(positions) { const nPoints = positions.length; const flat = new Float64Array(nPoints * 3); for (let index = 0; index < nPoints; index++) { const p = positions[index]; if (!p) continue; flat[index * 3] = p[0]; flat[index * 3 + 1] = p[1]; flat[index * 3 + 2] = p[2]; } const lines = new Uint32Array(nPoints + 1); lines[0] = nPoints; for (let index = 0; index < nPoints; index++) lines[index + 1] = index; const polyData = _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(); polyData.getPoints().setData(flat, 3); polyData.getLines().setData(lines); return polyData; } function buildCumulativeDistances(positions) { const nPoints = positions.length; const cumulativeDistances = new Float32Array(nPoints); let total = 0; for (let index = 1; index < nPoints; index++) { const previous = positions[index - 1]; const current = positions[index]; if (!previous || !current) continue; total += gl_matrix__WEBPACK_IMPORTED_MODULE_4__.dist(previous, current); cumulativeDistances[index] = total; } return { cumulativeDistances, totalLength: total }; } /** Central-difference unit tangent at `index`; false when degenerate. */ function centralTangent(out, positions, index) { const previous = positions[Math.max(0, index - 1)]; const next = positions[Math.min(positions.length - 1, index + 1)]; if (!previous || !next) return false; gl_matrix__WEBPACK_IMPORTED_MODULE_4__.sub(out, next, previous); if (gl_matrix__WEBPACK_IMPORTED_MODULE_4__.length(out) < 1e-9) return false; gl_matrix__WEBPACK_IMPORTED_MODULE_4__.normalize(out, out); return true; } /** The first frame: world-axis-projected up, exactly the pre-transport construction. */ function seedFrame(out, T) { const up = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(); pickUpAxis(up, T); const unitY = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_4__.scaleAndAdd(unitY, up, T, -gl_matrix__WEBPACK_IMPORTED_MODULE_4__.dot(up, T)); gl_matrix__WEBPACK_IMPORTED_MODULE_4__.normalize(unitY, unitY); const unitX = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_4__.cross(unitX, unitY, T); gl_matrix__WEBPACK_IMPORTED_MODULE_4__.normalize(unitX, unitX); // gl-matrix mat3 is column-major, so m[0..2]=col0, m[3..5]=col1, m[6..8]=col2. const m = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(); m[0] = unitX[0]; m[1] = unitX[1]; m[2] = unitX[2]; m[3] = unitY[0]; m[4] = unitY[1]; m[5] = unitY[2]; m[6] = T[0]; m[7] = T[1]; m[8] = T[2]; gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromMat3(out, m); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(out, out); } function buildParallelTransportFrames(positions) { const n = positions.length; const frames = new Float32Array(n * 4); const T = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(); const previousT = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(); const q = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(0, 0, 0, 1); const step = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); let seeded = false; for (let index = 0; index < n; index++) { // A degenerate tangent carries the neighbouring frame forward unchanged. if (centralTangent(T, positions, index)) { if (seeded) { gl_matrix__WEBPACK_IMPORTED_MODULE_3__.rotationTo(step, previousT, T); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.multiply(q, step, q); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(q, q); } else { seedFrame(q, T); seeded = true; // Points before the first usable tangent share the seed frame. for (let back = 0; back < index; back++) writeQuat(frames, back, q); } gl_matrix__WEBPACK_IMPORTED_MODULE_4__.copy(previousT, T); } writeQuat(frames, index, q); } return frames; } function writeQuat(target, index, q) { target[index * 4] = q[0]; target[index * 4 + 1] = q[1]; target[index * 4 + 2] = q[2]; target[index * 4 + 3] = q[3]; } function readQuat(out, source, index) { return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.set(out, source[index * 4], source[index * 4 + 1], source[index * 4 + 2], source[index * 4 + 3]); } /** * Transport around a closed path returns the end frame rotated about the shared * tangent (the path's holonomy). A closed spline's path repeats its first point * at the end, so without a correction the two ribbon ends disagree at the seam. * Unroll the residual twist proportionally along the arc. */ function distributeClosedPathTwist(positions, frames, cumulativeDistances, totalLength) { const n = positions.length; const first = positions[0]; const last = positions[n - 1]; if (n < 3 || totalLength <= 0 || !first || !last) return; if (gl_matrix__WEBPACK_IMPORTED_MODULE_4__.dist(first, last) > 1e-6) return; const seed = readQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), frames, 0); const end = readQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), frames, n - 1); const relative = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.multiply(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_3__.invert(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), end), seed); if (relative[3] < 0) gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(relative, relative, -1); // The twist half of a swing-twist split about local Z; the swing part is only // the endpoints' one-sided tangent estimates disagreeing, and stays. const twist = 2 * Math.atan2(relative[2], relative[3]); if (Math.abs(twist) < 1e-9) return; const roll = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); const q = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); for (let index = 1; index < n; index++) { const fraction = cumulativeDistances[index] / totalLength; gl_matrix__WEBPACK_IMPORTED_MODULE_3__.setAxisAngle(roll, [0, 0, 1], twist * fraction); readQuat(q, frames, index); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.multiply(q, q, roll); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(q, q); writeQuat(frames, index, q); } } function writeOrientationArray(polyData, frames, rollRad) { const n = frames.length / 4; const orientations = new Float32Array(n * 4); const roll = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), [0, 0, 1], rollRad); const frame = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); const q = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); const previous = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); for (let index = 0; index < n; index++) { gl_matrix__WEBPACK_IMPORTED_MODULE_3__.set(frame, frames[index * 4], frames[index * 4 + 1], frames[index * 4 + 2], frames[index * 4 + 3]); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.multiply(q, frame, roll); // The mapper interpolates raw components between points; a sign flip would // sweep the interpolant through zero, so keep neighbours in one hemisphere. if (index > 0 && gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dot(q, previous) < 0) gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(q, q, -1); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.copy(previous, q); writeQuat(orientations, index, q); } const pointData = polyData.getPointData(); const existing = pointData.getArrayByName?.(CPR_ORIENTATION_ARRAY_NAME); if (existing) { existing.setData(orientations); } else { pointData.addArray(_kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ name: CPR_ORIENTATION_ARRAY_NAME, numberOfComponents: 4, values: orientations })); } polyData.modified(); } function sampleCenterlineAt(centerline, distance, rollRad = 0) { const { cumulativeDistances, frames, positions, totalLength } = centerline; const n = positions.length; if (n < 2) return undefined; const clamped = Math.max(0, Math.min(distance, totalLength)); let index1 = 1; while (index1 < n && cumulativeDistances[index1] < clamped) index1++; if (index1 >= n) index1 = n - 1; const index0 = Math.max(0, index1 - 1); const d0 = cumulativeDistances[index0]; const d1 = cumulativeDistances[index1]; const segDelta = d1 - d0; const t = segDelta > 1e-9 ? (clamped - d0) / segDelta : 0; const p0 = positions[index0]; const p1 = positions[index1]; if (!p0 || !p1) return undefined; const position = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.fromValues(p0[0] * (1 - t) + p1[0] * t, p0[1] * (1 - t) + p1[1] * t, p0[2] * (1 - t) + p1[2] * t); const q0 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(frames[index0 * 4], frames[index0 * 4 + 1], frames[index0 * 4 + 2], frames[index0 * 4 + 3]); const q1 = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(frames[index1 * 4], frames[index1 * 4 + 1], frames[index1 * 4 + 2], frames[index1 * 4 + 3]); if (gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dot(q0, q1) < 0) gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(q1, q1, -1); const q = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.slerp(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), q0, q1, t); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(q, q); const tangent = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.transformQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(), [0, 0, 1], q); const viewUp = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.transformQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(), [0, 1, 0], q); const rolled = rollRad === 0 ? q : frameWithRoll(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), q, rollRad); const lateral = gl_matrix__WEBPACK_IMPORTED_MODULE_4__.transformQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_4__.create(), [1, 0, 0], rolled); return { lateral, position, tangent, viewUp }; } // Pick the world axis with the smallest component in T — the one most // orthogonal to T. Seeds the transported frame; avoids the degenerate frame from // a fixed-axis pick when T happens to align with that axis (e.g. the prototype's // hardcoded world-Z collapses on spine-aligned splines). Exported for testability. function pickUpAxis(out, T) { const absX = Math.abs(T[0]); const absY = Math.abs(T[1]); const absZ = Math.abs(T[2]); if (absX <= absY && absX <= absZ) { out[0] = 1; out[1] = 0; out[2] = 0; } else if (absY <= absX && absY <= absZ) { out[0] = 0; out[1] = 1; out[2] = 0; } else { out[0] = 0; out[1] = 0; out[2] = 1; } } /***/ }, /***/ 20974 /*!******************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/ct-popover.service.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CtPopoverService: () => (/* binding */ CtPopoverService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./viewport-ids */ 85309); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./volume-viewer-orchestrator.service */ 66035); const customPresetGroup = { items: [], label: `${_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_WINDOW_PRESET.name.toUpperCase()} PRESET` }; const defaultPresetGroup = { items: [], label: 'DICOM PRESET' }; const tvctPresetGroup = { items: [], label: 'TVCT PRESET' }; class CtPopoverService { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_6__.getLogger)(CtPopoverService.name); viewerOrchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_8__.VolumeViewerOrchestrator); renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.renderSettingsStore); engine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.RenderingEngineService); seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('', ...(ngDevMode ? [{ debugName: "seriesUid" }] : [])); get scalarRange() { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.getVolumeScalarRange)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.getViewport)(this.engine.ENGINE_ID, _viewport_ids__WEBPACK_IMPORTED_MODULE_7__.VIEWPORT_IDS.AXIAL)); } getCtFormConfig() { const seriesWindow = this.viewerOrchestrator.seriesWindowState(this.seriesUid()); if (!seriesWindow) { this.log.warn(`Series window state not found for series UID: ${this.seriesUid()}`); return []; } const [scalarMin, scalarMax] = this.scalarRange; const windowSettings = this.renderSettingsStore.windowSettings(); const option = preset => ({ label: `${preset.name} ${preset.level}/${preset.width}`, value: preset.name }); // eslint-disable-next-line sonarjs/cyclomatic-complexity const options = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { customPresetGroup.items = []; defaultPresetGroup.items = []; tvctPresetGroup.items = []; for (const { name } of this.renderSettingsStore.windowPresets()) { const volumeRenderPresets = this.renderSettingsStore.windowPresets(); const preset = volumeRenderPresets.find(preset => preset.name === name); if (name === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_WINDOW_PRESET.name && preset) { customPresetGroup.items = [...customPresetGroup.items, option(preset)]; } if (name.includes(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_PRESET_NAME) && preset) { defaultPresetGroup.items = [...defaultPresetGroup.items, option(preset)]; } if (!name.includes(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_PRESET_NAME) && name !== _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_WINDOW_PRESET.name && preset) { tvctPresetGroup.items = [...tvctPresetGroup.items, option(preset)]; } } return [customPresetGroup.items.length > 0 ? { ...customPresetGroup } : [], defaultPresetGroup.items.length > 0 ? { ...defaultPresetGroup } : [], tvctPresetGroup.items.length > 0 ? { ...tvctPresetGroup } : []]; }, ...(ngDevMode ? [{ debugName: "options" }] : [])); const config = [{ defaultValue: windowSettings.name, group: true, label: 'ctImageSettings.selectPreset', name: 'selectedPresetName', onChange: ctForm => { this.renderSettingsStore.selectWindowPreset(ctForm.selectedPresetName().value()); }, options, selectOptionsTemplate: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SelectOptionsTemplate.CT_SELECT_OPTIONS, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SELECT }, { defaultValue: windowSettings.width, label: 'ctImageSettings.windowWidth', max: Math.max(1, (scalarMax - scalarMin) * 2), min: 1, name: 'windowWidth', onChange: ctForm => { this.renderSettingsStore.updateCustomPreset({ width: ctForm.windowWidth().value() }); }, resetEvent: form => { const width = seriesWindow.defaultWindowWidth; this.renderSettingsStore.updateCustomPreset({ width }); form.windowWidth().value.set(width); }, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: windowSettings.level, label: 'ctImageSettings.windowLevel', max: scalarMax, min: scalarMin, name: 'windowLevel', onChange: ctForm => { this.renderSettingsStore.updateCustomPreset({ level: ctForm.windowLevel().value() }); }, resetEvent: form => { const level = seriesWindow.defaultWindowLevel; this.renderSettingsStore.updateCustomPreset({ level }); form.windowLevel().value.set(level); }, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }]; return config; } static ɵfac = function CtPopoverService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CtPopoverService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: CtPopoverService, factory: CtPopoverService.ɵfac }); } /***/ }, /***/ 50108 /*!***************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/endo-dev-panel/endo-dev-panel.component.ts ***! \***************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EndoDevelopmentPanelComponent: () => (/* binding */ EndoDevelopmentPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_divider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/divider */ 1432); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/core */ 14975); const ENDO = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VolumeRenderingOption.ENDO]; class EndoDevelopmentPanelComponent { settings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.renderSettingsStore); orchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_9__.VolumeViewerOrchestrator); ENDO = ENDO; airTissueThreshold = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.airTissueThreshold, ...(ngDevMode ? [{ debugName: "airTissueThreshold" }] : [])); tissueBloodThreshold = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.tissueBloodThreshold, ...(ngDevMode ? [{ debugName: "tissueBloodThreshold" }] : [])); bloodCalciumThreshold = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.bloodCalciumThreshold, ...(ngDevMode ? [{ debugName: "bloodCalciumThreshold" }] : [])); opacityTransitionWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.opacityTransitionWidth, ...(ngDevMode ? [{ debugName: "opacityTransitionWidth" }] : [])); rgbTransitionWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.rgbTransitionWidth, ...(ngDevMode ? [{ debugName: "rgbTransitionWidth" }] : [])); ambient = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.ambient, ...(ngDevMode ? [{ debugName: "ambient" }] : [])); diffuse = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.diffuse, ...(ngDevMode ? [{ debugName: "diffuse" }] : [])); specular = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.specular, ...(ngDevMode ? [{ debugName: "specular" }] : [])); specularPower = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(ENDO.specularPower, ...(ngDevMode ? [{ debugName: "specularPower" }] : [])); constructor() { const initialSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.settings.volumeSettings()); if (initialSettings.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VolumeRenderingOption.ENDO) { this.airTissueThreshold.set(initialSettings.airTissueThreshold); this.tissueBloodThreshold.set(initialSettings.tissueBloodThreshold); this.bloodCalciumThreshold.set(initialSettings.bloodCalciumThreshold); this.opacityTransitionWidth.set(initialSettings.opacityTransitionWidth); this.rgbTransitionWidth.set(initialSettings.rgbTransitionWidth); this.ambient.set(initialSettings.ambient); this.diffuse.set(initialSettings.diffuse); this.specular.set(initialSettings.specular); this.specularPower.set(initialSettings.specularPower); } (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const airTissueThreshold = this.airTissueThreshold(); const tissueBloodThreshold = this.tissueBloodThreshold(); const bloodCalciumThreshold = this.bloodCalciumThreshold(); const opacityTransitionWidth = this.opacityTransitionWidth(); const rgbTransitionWidth = this.rgbTransitionWidth(); const ambient = this.ambient(); const diffuse = this.diffuse(); const specular = this.specular(); const specularPower = this.specularPower(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.settings.updateVolumeSettings({ airTissueThreshold, ambient, bloodCalciumThreshold, diffuse, opacityTransitionWidth, rgbTransitionWidth, specular, specularPower, tissueBloodThreshold })); }); } static ɵfac = function EndoDevelopmentPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EndoDevelopmentPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdefineComponent"]({ type: EndoDevelopmentPanelComponent, selectors: [["lib-endo-dev-panel"]], decls: 83, vars: 54, consts: [[1, "ring-surface-700", "bg-surface-900/95", "max-h-[80vh]", "w-[480px]", "overflow-y-auto", "rounded-lg", "p-4", "shadow-2xl", "ring-1"], [1, "text-color", "mb-3", "text-sm", "font-semibold"], [1, "text-surface-400", "mb-2", "text-xs", "tracking-wide", "uppercase"], [1, "grid", "grid-cols-[120px_1fr_44px_auto]", "items-center", "gap-2", "py-1"], [1, "text-muted-color", "text-right", "text-xs"], ["dataTestIdOverride", "endo-dev-panel-slider-air-tissue", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], [1, "text-surface-200", "text-right", "font-mono", "text-xs", "tabular-nums"], ["data-test-id", "endo-dev-panel-p-button-air-tissue-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["icon", "refresh"], ["dataTestIdOverride", "endo-dev-panel-slider-tissue-blood", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-tissue-blood-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-blood-calcium", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-blood-calcium-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-opacity-transition", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-opacity-transition-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-rgb-transition", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-rgb-transition-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], [1, "my-3"], ["dataTestIdOverride", "endo-dev-panel-slider-ambient", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-ambient-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-diffuse", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-diffuse-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-specular", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-specular-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "endo-dev-panel-slider-specular-power", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "endo-dev-panel-p-button-specular-power-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"]], template: function EndoDevelopmentPanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "div", 0)(1, "p", 1); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](2, "Endo Preset Tuner"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](3, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](4, "Thresholds (HU)"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](5, "div", 3)(6, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](7, "Air / Tissue"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](8, "lib-slider", 5); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_8_listener($event) { return ctx.airTissueThreshold.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](9, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](11, "p-button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_11_listener() { return ctx.airTissueThreshold.set(ctx.ENDO.airTissueThreshold); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](12, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](13, "div", 3)(14, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](15, "Tissue / Blood"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](16, "lib-slider", 9); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_16_listener($event) { return ctx.tissueBloodThreshold.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](17, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](18); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](19, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_19_listener() { return ctx.tissueBloodThreshold.set(ctx.ENDO.tissueBloodThreshold); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](20, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](21, "div", 3)(22, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](23, "Blood / Calcium"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](24, "lib-slider", 11); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_24_listener($event) { return ctx.bloodCalciumThreshold.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](25, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](26); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](27, "p-button", 12); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_27_listener() { return ctx.bloodCalciumThreshold.set(ctx.ENDO.bloodCalciumThreshold); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](28, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](29, "div", 3)(30, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](31, "Opacity Trans."); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](32, "lib-slider", 13); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_32_listener($event) { return ctx.opacityTransitionWidth.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](33, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](34); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](35, "p-button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_35_listener() { return ctx.opacityTransitionWidth.set(ctx.ENDO.opacityTransitionWidth); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](36, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](37, "div", 3)(38, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](39, "RGB Trans."); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](40, "lib-slider", 15); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_40_listener($event) { return ctx.rgbTransitionWidth.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](41, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](42); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](43, "p-button", 16); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_43_listener() { return ctx.rgbTransitionWidth.set(ctx.ENDO.rgbTransitionWidth); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](44, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](45, "p-divider", 17); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](46, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](47, "Lighting"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](48, "div", 3)(49, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](50, "Ambient"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](51, "lib-slider", 18); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_51_listener($event) { return ctx.ambient.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](52, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](53); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](54, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](55, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_55_listener() { return ctx.ambient.set(ctx.ENDO.ambient); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](56, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](57, "div", 3)(58, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](59, "Diffuse"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](60, "lib-slider", 20); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_60_listener($event) { return ctx.diffuse.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](61, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](62); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](63, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](64, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_64_listener() { return ctx.diffuse.set(ctx.ENDO.diffuse); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](65, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](66, "div", 3)(67, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](68, "Specular"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](69, "lib-slider", 22); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_69_listener($event) { return ctx.specular.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](70, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](71); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](72, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](73, "p-button", 23); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_73_listener() { return ctx.specular.set(ctx.ENDO.specular); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](74, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](75, "div", 3)(76, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](77, "Spec. Power"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](78, "lib-slider", 24); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function EndoDevelopmentPanelComponent_Template_lib_slider_sliderChanged_78_listener($event) { return ctx.specularPower.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](79, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](80); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](81, "p-button", 25); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function EndoDevelopmentPanelComponent_Template_p_button_onClick_81_listener() { return ctx.specularPower.set(ctx.ENDO.specularPower); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](82, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", -1024)("sliderMax", 0)("sliderStep", 1)("sliderValue", ctx.airTissueThreshold()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.airTissueThreshold(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", -200)("sliderMax", 500)("sliderStep", 1)("sliderValue", ctx.tissueBloodThreshold()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.tissueBloodThreshold(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 100)("sliderMax", ctx.orchestrator.volumeMaxPixelValue())("sliderStep", 1)("sliderValue", ctx.bloodCalciumThreshold()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.bloodCalciumThreshold(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 300)("sliderStep", 1)("sliderValue", ctx.opacityTransitionWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.opacityTransitionWidth(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 300)("sliderStep", 1)("sliderValue", ctx.rgbTransitionWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.rgbTransitionWidth(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](9); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.ambient()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](54, 45, ctx.ambient(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.diffuse()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](63, 48, ctx.diffuse(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.specular()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](72, 51, ctx.specular(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 1)("sliderMax", 128)("sliderStep", 1)("sliderValue", ctx.specularPower()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.specularPower(), " "); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.SliderComponent, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, primeng_divider__WEBPACK_IMPORTED_MODULE_3__.Divider, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.IconComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_4__.Tooltip, _angular_common__WEBPACK_IMPORTED_MODULE_0__.DecimalPipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 77335 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/map-viewport-name-to-id.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ mapViewportNameToId: () => (/* binding */ mapViewportNameToId) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./viewport-ids */ 85309); const mapViewportNameToId = viewportName => { const mapping = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportName.AXIAL]: _viewport_ids__WEBPACK_IMPORTED_MODULE_1__.VIEWPORT_IDS.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportName.CORONAL]: _viewport_ids__WEBPACK_IMPORTED_MODULE_1__.VIEWPORT_IDS.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportName.REFORMAT]: _viewport_ids__WEBPACK_IMPORTED_MODULE_1__.VIEWPORT_IDS.REFORMAT, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportName.SAGITTAL]: _viewport_ids__WEBPACK_IMPORTED_MODULE_1__.VIEWPORT_IDS.SAGITTAL }; return mapping[viewportName]; }; /***/ }, /***/ 1894 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/orientation-form-config.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildOrientationFormConfig: () => (/* binding */ buildOrientationFormConfig) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Builds the rotation-slider config (CC/RL/AX) for the universal settings popover. */ function buildOrientationFormConfig(getCurrent, update, onDragStart, onDragEnd) { const target = getCurrent(); if (!target) return []; const angulation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationFromOrientation)(target.orientation); const setAxis = (axis, value, min, max) => { const current = getCurrent(); if (!current) return; const next = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.angulationFromOrientation)(current.orientation); next[axis] = Math.min(Math.max(value, min), max); update({ ...current, orientation: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.orientationFromAngulation)(next) }); }; const sliderField = (axis, label, min, max, valueFormatter) => ({ defaultValue: angulation[axis], label, max, min, name: axis, onChange: form => setAxis(axis, form[axis]().value(), min, max), onDragEnd, onDragStart, resetEvent: form => { setAxis(axis, 0, min, max); form[axis]().value.set(0); }, showValue: true, step: 1, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.SettingsPopoverField.SLIDER, valueFormatter, valueSuffix: '°' }); const config = [sliderField('cc', 'annotationMenu.editOrientation.craniocaudal', -90, 90, directionalAngle(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.formatCaudCran)), sliderField('rl', 'annotationMenu.editOrientation.raoLao', -180, 180, directionalAngle(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.formatRaoLao)), sliderField('ax', 'annotationMenu.editOrientation.axial', -180, 180)]; return config; } function directionalAngle(format) { return value => { const { direction, formattedValue } = format(Math.round(value)); return `${direction} ${formattedValue}`; }; } /***/ }, /***/ 21321 /*!*********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/provide-volume-viewer.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VOLUME_VIEWER_OPTIONS: () => (/* binding */ VOLUME_VIEWER_OPTIONS), /* harmony export */ provideVolumeViewer: () => (/* binding */ provideVolumeViewer) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _dicom_image_loader_dev__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../../dicom-image-loader-dev */ 99763); /* harmony import */ var _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../annotation-menu/annotation-menu-item.service */ 39860); /* harmony import */ var _annotation_menu_model_geometry_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../annotation-menu/model-geometry.service */ 27113); /* harmony import */ var _chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../chamber/chamber-menu/chamber-menu-item.service */ 44189); /* harmony import */ var _chamber_chamber_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../chamber/chamber.service */ 16592); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../colors/colors.service */ 39298); /* harmony import */ var _device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../device-sizing-chart/device-sizing-chart-dialog.service */ 26755); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _protocols_protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../protocols/protocol-creation-service/protocol-creation.service */ 88304); /* harmony import */ var _relative_measurements_relative_measurements_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../relative-measurements/relative-measurements.service */ 79408); /* harmony import */ var _s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../s-curve-relative-measurements/s-curve-relative-measurements.service */ 17464); /* harmony import */ var _sidebar_panels_services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../sidebar-panels/services/annotation-panel.service */ 56105); /* harmony import */ var _sidebar_panels_services_chamber_panel_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../sidebar-panels/services/chamber-panel.service */ 38164); /* harmony import */ var _camera_animation_service__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./camera-animation.service */ 76045); /* harmony import */ var _cpr_cpr_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./cpr/cpr.service */ 26144); /* harmony import */ var _ct_popover_service__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./ct-popover.service */ 20974); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./window-details/window-details.service */ 99360); // eslint-disable-next-line @nx/enforce-module-boundaries const VOLUME_VIEWER_OPTIONS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('VOLUME_VIEWER_OPTIONS'); function provideVolumeViewer(options) { return [{ provide: VOLUME_VIEWER_OPTIONS, useValue: options }, { provide: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.DICOM_IMAGE_LOADER, useValue: _dicom_image_loader_dev__WEBPACK_IMPORTED_MODULE_5__["default"] }, _colors_colors_service__WEBPACK_IMPORTED_MODULE_10__.ColorsService, _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_6__.AnnotationMenuItemService, _sidebar_panels_services_annotation_panel_service__WEBPACK_IMPORTED_MODULE_16__.AnnotationPanelService, _chamber_chamber_menu_chamber_menu_item_service__WEBPACK_IMPORTED_MODULE_8__.ChamberMenuItemService, _sidebar_panels_services_chamber_panel_service__WEBPACK_IMPORTED_MODULE_17__.ChamberPanelService, _chamber_chamber_service__WEBPACK_IMPORTED_MODULE_9__.ChamberService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.annotationStore, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.chamberStore, _camera_animation_service__WEBPACK_IMPORTED_MODULE_18__.CameraAnimationService, _cpr_cpr_service__WEBPACK_IMPORTED_MODULE_19__.CprService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.cprSessionStore, _ct_popover_service__WEBPACK_IMPORTED_MODULE_20__.CtPopoverService, _device_sizing_chart_device_sizing_chart_dialog_service__WEBPACK_IMPORTED_MODULE_11__.DeviceSizingChartDialogService, primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__.DialogService, _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_12__.InteractionModeService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.MeasurementService, _annotation_menu_model_geometry_service__WEBPACK_IMPORTED_MODULE_7__.ModelGeometryService, _protocols_protocol_creation_service_protocol_creation_service__WEBPACK_IMPORTED_MODULE_13__.ProtocolCreationService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.ProtocolFacade, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.protocolStore, _relative_measurements_relative_measurements_service__WEBPACK_IMPORTED_MODULE_14__.RelativeMeasurementsService, _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.RenderingEngineService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.renderSettingsStore, _s_curve_relative_measurements_s_curve_relative_measurements_service__WEBPACK_IMPORTED_MODULE_15__.SCurveRelativeMeasurementsService, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.sCurveStore, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.uiStore, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.viewportStore, _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.VolumeLoaderService, _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_21__.VolumeViewerOrchestrator, _tomoverse_store__WEBPACK_IMPORTED_MODULE_3__.volumeViewerStore, _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_22__.WindowDetailsService]; } /***/ }, /***/ 33032 /*!***********************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/render-quality-dev-panel/render-quality-dev-panel.component.ts ***! \***********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RenderQualityDevelopmentPanelComponent: () => (/* binding */ RenderQualityDevelopmentPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); class RenderQualityDevelopmentPanelComponent { orchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_2__.VolumeViewerOrchestrator); static ɵfac = function RenderQualityDevelopmentPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RenderQualityDevelopmentPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: RenderQualityDevelopmentPanelComponent, selectors: [["lib-render-quality-dev-panel"]], decls: 9, vars: 5, consts: [[1, "ring-surface-700", "bg-surface-900/95", "w-[320px]", "rounded-lg", "p-4", "shadow-2xl", "ring-1"], [1, "text-color", "mb-3", "text-sm", "font-semibold"], [1, "grid", "grid-cols-[100px_1fr_44px]", "items-center", "gap-2", "py-1"], [1, "text-muted-color", "text-right", "text-xs"], ["dataTestIdOverride", "render-quality-dev-panel-slider-idle-quality", "name", "render-quality-idle-quality", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], [1, "text-surface-200", "text-right", "font-mono", "text-xs", "tabular-nums"]], template: function RenderQualityDevelopmentPanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 0)(1, "p", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](2, "Idle Render Quality"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](3, "div", 2)(4, "span", 3); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](5, "Max Quality"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](6, "lib-slider", 4); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("sliderChanged", function RenderQualityDevelopmentPanelComponent_Template_lib_slider_sliderChanged_6_listener($event) { return ctx.orchestrator.idleImageQuality.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](7, "span", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 100)("sliderStep", 1)("sliderValue", ctx.orchestrator.idleImageQuality()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", ctx.orchestrator.idleImageQuality(), " "); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_1__.SliderComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 57669 /*!*****************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/s-curve-graph-popover.service.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveGraphPopoverService: () => (/* binding */ SCurveGraphPopoverService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); const FONT_SIZE_MIN = 6; const FONT_SIZE_MAX = 16; const LINE_WIDTH_MIN = 0.5; const LINE_WIDTH_MAX = 8; class SCurveGraphPopoverService { renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.renderSettingsStore); formConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => [{ defaultValue: this.renderSettingsStore.sCurveGraphFontSize(), label: 'sCurveGraphSettings.fontSize', max: FONT_SIZE_MAX, min: FONT_SIZE_MIN, name: 'fontSize', onChange: form => { this.renderSettingsStore.setSCurveGraphFontSize(form.fontSize().value()); }, resetEvent: form => { this.renderSettingsStore.setSCurveGraphFontSize(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE); form.fontSize().value.set(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE); }, step: 0.1, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: this.renderSettingsStore.sCurveLineWidth(), label: 'sCurveGraphSettings.lineWidth', max: LINE_WIDTH_MAX, min: LINE_WIDTH_MIN, name: 'lineWidth', onChange: form => { this.renderSettingsStore.setSCurveLineWidth(form.lineWidth().value()); }, resetEvent: form => { this.renderSettingsStore.setSCurveLineWidth(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_LINE_WIDTH); form.lineWidth().value.set(_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_LINE_WIDTH); }, step: 0.1, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: this.renderSettingsStore.sCurveShowChamberPoints(), label: 'sCurveGraphSettings.showChamberPoints', name: 'showChamberPoints', onChange: form => { this.renderSettingsStore.setSCurveShowChamberPoints(form.showChamberPoints().value()); }, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.TOGGLE }], ...(ngDevMode ? [{ debugName: "formConfig" }] : [])); static ɵfac = function SCurveGraphPopoverService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveGraphPopoverService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: SCurveGraphPopoverService, factory: SCurveGraphPopoverService.ɵfac }); } /***/ }, /***/ 74278 /*!***********************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/vascular-dev-panel/vascular-dev-panel.component.ts ***! \***********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VascularDevelopmentPanelComponent: () => (/* binding */ VascularDevelopmentPanelComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_divider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/divider */ 1432); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/core */ 14975); function VascularDevelopmentPanelComponent_Case_120_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "p-button", 37); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Case_120_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.orchestrator.revertVascularMask()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); } } function VascularDevelopmentPanelComponent_Case_121_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "div", 35)(1, "p-button", 38); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Case_121_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.orchestrator.acceptVascularMask()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](2, "p-button", 39); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Case_121_Template_p_button_onClick_2_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.orchestrator.refuseVascularMask()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("disabled", ctx_r1.orchestrator.vascularMaskComputing()); } } function VascularDevelopmentPanelComponent_Case_122_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "p-button", 40); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Case_122_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r1.previewSegmentation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); } } const VASCULAR = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VolumeRenderingOption.VASCULAR]; class VascularDevelopmentPanelComponent { settings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_6__.renderSettingsStore); orchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_9__.VolumeViewerOrchestrator); VASCULAR = VASCULAR; tissueBloodThreshold = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.tissueBloodThreshold, ...(ngDevMode ? [{ debugName: "tissueBloodThreshold" }] : [])); bloodCalciumThreshold = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.bloodCalciumThreshold, ...(ngDevMode ? [{ debugName: "bloodCalciumThreshold" }] : [])); opacityTransitionWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.opacityTransitionWidth, ...(ngDevMode ? [{ debugName: "opacityTransitionWidth" }] : [])); outlierOpacity = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.outlierOpacity, ...(ngDevMode ? [{ debugName: "outlierOpacity" }] : [])); ambient = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.ambient, ...(ngDevMode ? [{ debugName: "ambient" }] : [])); diffuse = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.diffuse, ...(ngDevMode ? [{ debugName: "diffuse" }] : [])); specular = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.specular, ...(ngDevMode ? [{ debugName: "specular" }] : [])); specularPower = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.specularPower, ...(ngDevMode ? [{ debugName: "specularPower" }] : [])); clusterSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.clusterSize, ...(ngDevMode ? [{ debugName: "clusterSize" }] : [])); erosionRadius = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.erosionRadius, ...(ngDevMode ? [{ debugName: "erosionRadius" }] : [])); gridStep = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.gridStep, ...(ngDevMode ? [{ debugName: "gridStep" }] : [])); minHU = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.minHU, ...(ngDevMode ? [{ debugName: "minHU" }] : [])); maxHU = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(VASCULAR.maxHU, ...(ngDevMode ? [{ debugName: "maxHU" }] : [])); constructor() { const initialSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.settings.volumeSettings()); if (initialSettings.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VolumeRenderingOption.VASCULAR) { this.tissueBloodThreshold.set(initialSettings.tissueBloodThreshold); this.bloodCalciumThreshold.set(initialSettings.bloodCalciumThreshold); this.opacityTransitionWidth.set(initialSettings.opacityTransitionWidth); this.outlierOpacity.set(initialSettings.outlierOpacity); this.gridStep.set(initialSettings.gridStep); this.clusterSize.set(initialSettings.clusterSize); this.erosionRadius.set(initialSettings.erosionRadius); this.minHU.set(initialSettings.minHU); this.maxHU.set(initialSettings.maxHU); this.ambient.set(initialSettings.ambient); this.diffuse.set(initialSettings.diffuse); this.specular.set(initialSettings.specular); this.specularPower.set(initialSettings.specularPower); } // Sync local signals from the store so changes made via the settings popover are reflected here. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const settings = this.settings.volumeSettings(); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VolumeRenderingOption.VASCULAR) return; (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { this.clusterSize.set(settings.clusterSize); this.erosionRadius.set(settings.erosionRadius); this.minHU.set(settings.minHU); this.maxHU.set(settings.maxHU); this.gridStep.set(settings.gridStep); this.tissueBloodThreshold.set(settings.tissueBloodThreshold); this.bloodCalciumThreshold.set(settings.bloodCalciumThreshold); this.opacityTransitionWidth.set(settings.opacityTransitionWidth); this.outlierOpacity.set(settings.outlierOpacity); this.ambient.set(settings.ambient); this.diffuse.set(settings.diffuse); this.specular.set(settings.specular); this.specularPower.set(settings.specularPower); }); }); // gridStep and clusterSize are excluded — they only take effect on slide end // and require a WebWorker recompute, not a live render update. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const tissueBloodThreshold = this.tissueBloodThreshold(); const bloodCalciumThreshold = this.bloodCalciumThreshold(); const opacityTransitionWidth = this.opacityTransitionWidth(); const outlierOpacity = this.outlierOpacity(); const ambient = this.ambient(); const diffuse = this.diffuse(); const specular = this.specular(); const specularPower = this.specularPower(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.settings.updateVolumeSettings({ ambient, bloodCalciumThreshold, diffuse, opacityTransitionWidth, outlierOpacity, specular, specularPower, tissueBloodThreshold })); }); } /** The orchestrator coalesces drag ticks and drops them outside preview state. */ onSegmentationParameterDrag() { this.orchestrator.previewVascularMaskLive({ clusterSize: this.clusterSize(), erosionRadius: this.erosionRadius(), gridStep: this.gridStep(), maxHU: this.maxHU(), minHU: this.minHU() }); } onThresholdSlideEnd() { this.settings.updateVolumeSettings({ clusterSize: this.clusterSize(), erosionRadius: this.erosionRadius(), gridStep: this.gridStep(), maxHU: this.maxHU(), minHU: this.minHU() }); if (this.orchestrator.vascularSegmentationState() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_5__.VascularSegmentationState.PREVIEWING) { this.orchestrator.previewVascularMask(); } } previewSegmentation() { this.onThresholdSlideEnd(); this.orchestrator.previewVascularMask(); } static ɵfac = function VascularDevelopmentPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VascularDevelopmentPanelComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdefineComponent"]({ type: VascularDevelopmentPanelComponent, selectors: [["lib-vascular-dev-panel"]], decls: 123, vars: 78, consts: [[1, "ring-surface-700", "bg-surface-900/95", "max-h-[80vh]", "w-[480px]", "overflow-y-auto", "rounded-lg", "p-4", "shadow-2xl", "ring-1"], [1, "text-color", "mb-3", "text-sm", "font-semibold"], [1, "text-surface-400", "mb-2", "text-xs", "tracking-wide", "uppercase"], [1, "grid", "grid-cols-[120px_1fr_44px_auto]", "items-center", "gap-2", "py-1"], [1, "text-muted-color", "text-right", "text-xs"], ["dataTestIdOverride", "vascular-dev-panel-slider-tissue-blood", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], [1, "text-surface-200", "text-right", "font-mono", "text-xs", "tabular-nums"], ["data-test-id", "vascular-dev-panel-p-button-tissue-blood-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["icon", "refresh"], ["dataTestIdOverride", "vascular-dev-panel-slider-blood-calcium", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-blood-calcium-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], [1, "my-3"], ["dataTestIdOverride", "vascular-dev-panel-slider-min-hu", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-min-hu-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-max-hu", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-max-hu-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-opacity-transition", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-opacity-transition-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-outlier-opacity", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-outlier-opacity-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-grid-step", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-grid-step-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-cluster-size", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-cluster-size-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-erosion-radius", 3, "sliderChanged", "slideEnd", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-erosion-radius-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-ambient", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-ambient-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-diffuse", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-diffuse-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-specular", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-specular-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["dataTestIdOverride", "vascular-dev-panel-slider-specular-power", 3, "sliderChanged", "sliderMin", "sliderMax", "sliderStep", "sliderValue"], ["data-test-id", "vascular-dev-panel-p-button-specular-power-reset", "text", "", "size", "small", "severity", "secondary", "pTooltip", "Reset", 3, "onClick"], ["data-test-id", "vascular-dev-panel-p-button-revert-segmentation", "label", "Revert Segmentation", "fluid", "", "size", "small", "severity", "secondary"], [1, "flex", "gap-2"], ["data-test-id", "vascular-dev-panel-p-button-preview-segmentation", "label", "Preview Segmentation", "fluid", "", "size", "small"], ["data-test-id", "vascular-dev-panel-p-button-revert-segmentation", "label", "Revert Segmentation", "fluid", "", "size", "small", "severity", "secondary", 3, "onClick"], ["data-test-id", "vascular-dev-panel-p-button-accept-segmentation", "label", "Accept", "fluid", "", "size", "small", 3, "onClick", "disabled"], ["data-test-id", "vascular-dev-panel-p-button-refuse-segmentation", "label", "Refuse", "fluid", "", "size", "small", "severity", "secondary", 3, "onClick"], ["data-test-id", "vascular-dev-panel-p-button-preview-segmentation", "label", "Preview Segmentation", "fluid", "", "size", "small", 3, "onClick"]], template: function VascularDevelopmentPanelComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](0, "div", 0)(1, "p", 1); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](2, "Vascular Render Tuner"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](3, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](4, "Thresholds (HU)"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](5, "div", 3)(6, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](7, "Tissue / Blood"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](8, "lib-slider", 5); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_8_listener($event) { ctx.tissueBloodThreshold.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_8_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](9, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](11, "p-button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_11_listener() { ctx.tissueBloodThreshold.set(ctx.VASCULAR.tissueBloodThreshold); return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](12, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](13, "div", 3)(14, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](15, "Blood / Calcium"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](16, "lib-slider", 9); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_16_listener($event) { ctx.bloodCalciumThreshold.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_16_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](17, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](18); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](19, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_19_listener() { ctx.bloodCalciumThreshold.set(ctx.VASCULAR.bloodCalciumThreshold); return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](20, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](21, "p-divider", 11); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](22, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](23, "Segmentation"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](24, "div", 3)(25, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](26, "Min HU"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](27, "lib-slider", 12); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_27_listener($event) { ctx.minHU.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_27_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](28, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](29); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](30, "p-button", 13); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_30_listener() { ctx.minHU.set(ctx.VASCULAR.minHU); return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](31, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](32, "div", 3)(33, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](34, "Max HU"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](35, "lib-slider", 14); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_35_listener($event) { return ctx.maxHU.set($event); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_35_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](36, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](37); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](38, "p-button", 15); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_38_listener() { ctx.maxHU.set(ctx.VASCULAR.maxHU); return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](39, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](40, "div", 3)(41, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](42, "Opacity Trans."); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](43, "lib-slider", 16); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_43_listener($event) { ctx.opacityTransitionWidth.set($event); return ctx.onSegmentationParameterDrag(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](44, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](45); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](46, "p-button", 17); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_46_listener() { return ctx.opacityTransitionWidth.set(ctx.VASCULAR.opacityTransitionWidth); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](47, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](48, "div", 3)(49, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](50, "Outlier Opacity"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](51, "lib-slider", 18); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_51_listener($event) { ctx.outlierOpacity.set($event); return ctx.onSegmentationParameterDrag(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](52, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](53); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](54, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](55, "p-button", 19); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_55_listener() { return ctx.outlierOpacity.set(ctx.VASCULAR.outlierOpacity); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](56, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](57, "div", 3)(58, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](59, "Grid step"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](60, "lib-slider", 20); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_60_listener($event) { ctx.gridStep.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_60_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](61, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](62); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](63, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_63_listener() { return ctx.gridStep.set(ctx.VASCULAR.gridStep); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](64, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](65, "div", 3)(66, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](67, "Cluster size filter"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](68, "lib-slider", 22); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_68_listener($event) { ctx.clusterSize.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_68_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](69, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](70); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](71, "p-button", 23); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_71_listener() { return ctx.clusterSize.set(ctx.VASCULAR.clusterSize); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](72, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](73, "div", 3)(74, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](75, "Erosion radius"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](76, "lib-slider", 24); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_76_listener($event) { ctx.erosionRadius.set($event); return ctx.onSegmentationParameterDrag(); })("slideEnd", function VascularDevelopmentPanelComponent_Template_lib_slider_slideEnd_76_listener() { return ctx.onThresholdSlideEnd(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](77, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](78); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](79, "p-button", 25); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_79_listener() { return ctx.erosionRadius.set(ctx.VASCULAR.erosionRadius); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](80, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](81, "p-divider", 11); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](82, "p", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](83, "Lighting"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](84, "div", 3)(85, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](86, "Ambient"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](87, "lib-slider", 26); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_87_listener($event) { return ctx.ambient.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](88, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](89); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](90, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](91, "p-button", 27); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_91_listener() { return ctx.ambient.set(ctx.VASCULAR.ambient); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](92, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](93, "div", 3)(94, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](95, "Diffuse"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](96, "lib-slider", 28); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_96_listener($event) { return ctx.diffuse.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](97, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](98); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](99, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](100, "p-button", 29); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_100_listener() { return ctx.diffuse.set(ctx.VASCULAR.diffuse); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](101, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](102, "div", 3)(103, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](104, "Specular"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](105, "lib-slider", 30); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_105_listener($event) { return ctx.specular.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](106, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](107); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipe"](108, "number"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](109, "p-button", 31); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_109_listener() { return ctx.specular.set(ctx.VASCULAR.specular); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](110, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](111, "div", 3)(112, "span", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](113, "Spec. Power"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](114, "lib-slider", 32); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("sliderChanged", function VascularDevelopmentPanelComponent_Template_lib_slider_sliderChanged_114_listener($event) { return ctx.specularPower.set($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](115, "span", 6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtext"](116); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementStart"](117, "p-button", 33); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵlistener"]("onClick", function VascularDevelopmentPanelComponent_Template_p_button_onClick_117_listener() { return ctx.specularPower.set(ctx.VASCULAR.specularPower); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](118, "lib-icon", 8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelement"](119, "p-divider", 11); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditionalCreate"](120, VascularDevelopmentPanelComponent_Case_120_Template, 1, 0, "p-button", 34)(121, VascularDevelopmentPanelComponent_Case_121_Template, 3, 1, "div", 35)(122, VascularDevelopmentPanelComponent_Case_122_Template, 1, 0, "p-button", 36); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_65_0; _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](8); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", ctx.orchestrator.volumeMinPixelValue())("sliderMax", ctx.bloodCalciumThreshold())("sliderStep", 1)("sliderValue", ctx.tissueBloodThreshold()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.tissueBloodThreshold(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", ctx.tissueBloodThreshold())("sliderMax", ctx.orchestrator.volumeMaxPixelValue())("sliderStep", 1)("sliderValue", ctx.bloodCalciumThreshold()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.bloodCalciumThreshold(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](9); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", ctx.orchestrator.volumeMinPixelValue())("sliderMax", ctx.bloodCalciumThreshold())("sliderStep", 1)("sliderValue", ctx.minHU()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.minHU(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", ctx.tissueBloodThreshold())("sliderMax", ctx.orchestrator.volumeMaxPixelValue())("sliderStep", 1)("sliderValue", ctx.maxHU()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.maxHU(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 300)("sliderStep", 1)("sliderValue", ctx.opacityTransitionWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.opacityTransitionWidth(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.outlierOpacity()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](54, 66, ctx.outlierOpacity(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 1)("sliderMax", 100)("sliderStep", 1)("sliderValue", ctx.gridStep()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.gridStep(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 1000)("sliderMax", 500000)("sliderStep", 1)("sliderValue", ctx.clusterSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.clusterSize(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 10)("sliderStep", 0.1)("sliderValue", ctx.erosionRadius()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.erosionRadius(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](9); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.ambient()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](90, 69, ctx.ambient(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.diffuse()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](99, 72, ctx.diffuse(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 0)("sliderMax", 1)("sliderStep", 0.01)("sliderValue", ctx.specular()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵpipeBind2"](108, 75, ctx.specular(), "1.2-2"), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](7); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵproperty"]("sliderMin", 1)("sliderMax", 128)("sliderStep", 1)("sliderValue", ctx.specularPower()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵtextInterpolate1"](" ", ctx.specularPower(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditional"]((tmp_65_0 = ctx.orchestrator.vascularSegmentationState()) === "applied" ? 120 : tmp_65_0 === "previewing" ? 121 : 122); } }, dependencies: [_tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.SliderComponent, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, primeng_divider__WEBPACK_IMPORTED_MODULE_3__.Divider, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_7__.IconComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_4__.Tooltip, _angular_common__WEBPACK_IMPORTED_MODULE_0__.DecimalPipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 85309 /*!************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-ids.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MPR_VIEWPORT_ID_LIST: () => (/* binding */ MPR_VIEWPORT_ID_LIST), /* harmony export */ NON_DEGRADING_VIEWPORT_ID_LIST: () => (/* binding */ NON_DEGRADING_VIEWPORT_ID_LIST), /* harmony export */ VIEWPORT_IDS: () => (/* binding */ VIEWPORT_IDS) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const VIEWPORT_IDS = { AXIAL: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.TOPLEFTMAIN, // 'viewportAxial', CORONAL: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.MIDDLEMAIN, // 'viewportCoronal', REFORMAT: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.RIGHTMAIN, // 'viewport3d', SAGITTAL: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportAxisState.BOTTOMLEFTMAIN // 'viewportSagittal', }; const MPR_VIEWPORT_ID_LIST = [VIEWPORT_IDS.AXIAL, VIEWPORT_IDS.CORONAL, VIEWPORT_IDS.SAGITTAL]; // Left-click in REFORMAT/CORONAL only changes the crosshair position without re-rendering // the 3D volume itself, so these viewports do not trigger quality degradation. const NON_DEGRADING_VIEWPORT_ID_LIST = [VIEWPORT_IDS.REFORMAT, VIEWPORT_IDS.CORONAL]; /***/ }, /***/ 34837 /*!***************************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/annotation-create-interaction.ts ***! \***************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationCreateInteraction: () => (/* binding */ AnnotationCreateInteraction) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); // 2x the default pick tolerance (see RenderingEngineService.getScreenPositionActor) - the // first point is a small, easy-to-miss target the user must deliberately re-hit to close // the shape, so it's worth being more forgiving here than the flat default used elsewhere. const FIRST_POINT_HIT_RADIUS = 10; /** * Handles clicks while in annotation creation mode. Depending on the type of * annotation, it may handle adding multiple points and deciding when an annotation * is complete. */ class AnnotationCreateInteraction { annotationFacade; colorsService; renderingEngineService; viewportStore; constructor(annotationFacade, colorsService, renderingEngineService, viewportStore) { this.annotationFacade = annotationFacade; this.colorsService = colorsService; this.renderingEngineService = renderingEngineService; this.viewportStore = viewportStore; } handle(screenPos, viewportId, annotationBeingCreated, isDoubleClick) { const worldPos = this.renderingEngineService.getWorldPosition(viewportId, screenPos); if (!worldPos) { this.annotationFacade.cancelAnnotationCreation(); return; } switch (annotationBeingCreated.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.ANGLE: { return this.angleBeingCreated(annotationBeingCreated, worldPos); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.CLOSED_SPLINE: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.OPEN_SPLINE: { return this.splineBeingCreated(annotationBeingCreated, screenPos, worldPos, isDoubleClick, viewportId); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.DISTANCE: { return this.distanceBeingCreated(annotationBeingCreated, worldPos); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.AnnotationSourceType.POINT: { return this.pointBeingCreated(annotationBeingCreated, worldPos); } default: { this.annotationFacade.cancelAnnotationCreation(); } } return undefined; } angleBeingCreated(angle, worldPos) { const update = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.show)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.appendPoint)(angle, [...worldPos])); this.annotationFacade.creatingAnnotation(update); this.setCrosshairPos([...worldPos]); if (update.points.length === 3) { this.creationComplete(); } return { annotationId: angle.id, pointIndex: update.points.length - 1 }; } distanceBeingCreated(distance, worldPos) { const update = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.show)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.appendPoint)(distance, [...worldPos])); this.annotationFacade.creatingAnnotation(update); this.setCrosshairPos([...worldPos]); if (update.points.length === 2) { this.creationComplete(); } return { annotationId: distance.id, pointIndex: update.points.length - 1 }; } pointBeingCreated(point, worldPos) { this.annotationFacade.creatingAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.show)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.move)(point, [...worldPos]))); this.setCrosshairPos([...worldPos]); this.creationComplete(); return { annotationId: point.id }; } splineBeingCreated(spline, screenPos, worldPos, isDoubleClick, viewportId) { if (isDoubleClick && (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__.getValid)(spline)) { this.creationComplete(); return; } // If the first point of the current spline is clicked, close it if (spline.points.length > 1 && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsClosedSpline)(spline) && this.isFirstPointHit(spline.id, viewportId, screenPos)) { this.creationComplete(); return; } // If points are too close, they can break spline interpolation const lastPoint = spline.points.at(-1); if (lastPoint && gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(lastPoint, worldPos) < 1) { return; } const update = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.show)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.appendPoint)(spline, [...worldPos])); this.annotationFacade.creatingAnnotation(update); this.setCrosshairPos([...worldPos]); return { annotationId: spline.id, pointIndex: update.points.length - 1 }; } /** Enter-to-finish: the same completion path double-click uses in splineBeingCreated, * gated the same way - a no-op until the annotation is actually valid (e.g. an open * spline needs at least 2 points). */ completeIfValid(annotation) { if (!(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_3__.getValid)(annotation)) return; this.creationComplete(); } /** Enter-to-finish for open/closed splines specifically: appends the mouse's current * world position as a final point first, then completes - unlike double-click, which * only completes with whatever points are already confirmed. Without this, the user * is left looking at a rubber-band preview extending to the cursor, and pressing Enter * would silently drop that last segment instead of placing it. Skips the append when * that position is redundant with the last confirmed point, the same guard a real * click uses in splineBeingCreated. */ completeSplineWithCurrentPosition(spline, worldPos) { const lastPoint = spline.points.at(-1); const tooClose = !!lastPoint && gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(lastPoint, worldPos) < 1; const current = tooClose ? spline : (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.show)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.appendPoint)(spline, [...worldPos])); if (!tooClose) this.annotationFacade.creatingAnnotation(current); this.completeIfValid(current); } creationComplete() { this.annotationFacade.annotationCreationComplete(); this.colorsService.nextColor(); } setCrosshairPos(pos) { this.viewportStore.updateIntersection(pos); } isFirstPointHit(annotationId, viewportId, screenPos) { const actor = this.renderingEngineService.getScreenPositionActor(viewportId, screenPos, FIRST_POINT_HIT_RADIUS); const details = this.getActorAnnotationDetails(actor); return details?.annotationId === annotationId && details.pointIndex === 0; } getActorAnnotationDetails(actor) { const properties = actor?.get('annotationId', 'pointIndex'); if (properties?.annotationId === undefined) { return; } return properties; } } /***/ }, /***/ 59821 /*!***************************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/annotation-select-interaction.ts ***! \***************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationSelectInteraction: () => (/* binding */ AnnotationSelectInteraction) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); class AnnotationSelectInteraction { annotationFacade; renderingEngineService; viewportStore; shellPicker; constructor(annotationFacade, renderingEngineService, viewportStore, shellPicker) { this.annotationFacade = annotationFacade; this.renderingEngineService = renderingEngineService; this.viewportStore = viewportStore; this.shellPicker = shellPicker; } handle(screenPos, viewportId, multiselect = false) { const hardwareActor = this.renderingEngineService.getScreenPositionActor(viewportId, screenPos); // On hardware-selector miss, ray-cast Object3D shells so clicks through holes still select. const actor = hardwareActor ?? this.fallbackPickObject3dShell(viewportId, screenPos); let details; if (!actor && !multiselect) { this.annotationFacade.deselectAllAnnotations(); } else { const { annotationId, pointIndex } = this.getActorAnnotationDetails(actor) ?? {}; if (annotationId) { if (multiselect) { this.annotationFacade.toggleSelectAnnotation(annotationId); } else { this.annotationFacade.selectAnnotations([annotationId]); } details = { annotationId, pointIndex }; } } // Move crosshair to control-point world position when clicking a point handle. const snapTarget = details?.pointIndex === undefined ? undefined : this.controlPointPosition(details.annotationId, details.pointIndex); const worldPos = snapTarget ?? this.renderingEngineService.getWorldPosition(viewportId, screenPos); if (worldPos) { this.setCrosshairPos(worldPos); } return details; } /** CPU picks when the hardware selector misses. Returns the back-most actor * along the click ray (3D) or the smallest-2D-AABB cross-section (MPR). */ fallbackPickObject3dShell(viewportId, screenPos) { for (const annotationId of this.shellPicker.pickShellAnnotationIds(viewportId, screenPos)) { const actor = this.findActorForAnnotation(viewportId, annotationId); if (actor) return actor; } return undefined; } findActorForAnnotation(viewportId, annotationId) { for (const actor of (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.getAnnotationActors)(viewportId)) { const properties = actor.get?.('annotationId'); if (properties?.annotationId === annotationId) return actor; } return undefined; } controlPointPosition(annotationId, pointIndex) { const annotation = this.annotationFacade.getAnnotationById(annotationId); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationHasPoints)(annotation)) { const point = annotation.points[pointIndex]; return point ? [...point] : undefined; } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationHasPosition)(annotation)) { return [...annotation.position]; } return undefined; } setCrosshairPos(pos) { this.viewportStore.updateIntersection(pos); } getActorAnnotationDetails(actor) { const properties = actor?.get('annotationId', 'pointIndex'); if (properties?.annotationId === undefined) { return; } return properties; } } /***/ }, /***/ 50295 /*!***************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/hover-interaction.ts ***! \***************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ HoverInteraction: () => (/* binding */ HoverInteraction) /* harmony export */ }); class HoverInteraction { renderingEngineService; shellPicker; hoverTimeout; constructor(renderingEngineService, shellPicker) { this.renderingEngineService = renderingEngineService; this.shellPicker = shellPicker; } /** * expandedFirstPointCheck widens the pick radius for one specific target (a closed * spline's first point while it's being created) rather than for hover generally - * widening the default for every actor would make unrelated nearby annotations start * hovering from farther away than intended. Falling back to it only when the normal- * radius pick misses also avoids fighting the point's own hover-triggered size increase: * without the wider fallback, the cursor can sit visually over the enlarged point but * just outside the flat default radius, causing hover to flicker on/off each frame. */ handle(screenPos, viewportId, hoveredAnnotationSignal, expandedFirstPointCheck) { if (this.hoverTimeout !== undefined) cancelAnimationFrame(this.hoverTimeout); this.hoverTimeout = requestAnimationFrame(() => { const actor = this.renderingEngineService.getScreenPositionActor(viewportId, screenPos); let details = this.getActorAnnotationDetails(actor); if (!details && expandedFirstPointCheck) { const widerActor = this.renderingEngineService.getScreenPositionActor(viewportId, screenPos, expandedFirstPointCheck.hitRadius); const widerDetails = this.getActorAnnotationDetails(widerActor); if (widerDetails?.annotationId === expandedFirstPointCheck.annotationId && widerDetails.pointIndex === 0) { details = widerDetails; } } hoveredAnnotationSignal.set(details ?? this.shellHoverDetails(viewportId, screenPos)); }); } shellHoverDetails(viewportId, screenPos) { const [annotationId] = this.shellPicker.pickShellAnnotationIds(viewportId, screenPos); return annotationId ? { annotationId } : undefined; } getActorAnnotationDetails(actor) { const properties = actor?.get('annotationId', 'pointIndex'); if (properties?.annotationId === undefined) { return; } return properties; } } /***/ }, /***/ 38112 /*!***********************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/object3d-drag-interaction.ts ***! \***********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3DDragInteraction: () => (/* binding */ Object3DDragInteraction) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /** Time constant (ms) for the grab-offset decay. */ const FOLLOW_TAU_MS = 80; /** Below this world-space offset magnitude the glide is treated as finished. */ const OFFSET_EPSILON = 0.05; /** * Eases an Object3D into a move-drag. * * On the first move of a gesture we record the gap between the model's position * and the cursor as a decaying offset, so the model glides from where it sat to * the cursor and then tracks it 1:1 with no steady-state lag. */ class Object3DDragInteraction { annotationFacade; annotationId; target = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); offset = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); hasTarget = false; rafId; lastFrameTime = 0; constructor(annotationFacade) { this.annotationFacade = annotationFacade; } get isActive() { return this.annotationId !== undefined; } update(annotationId, cursorWorld) { if (this.annotationId !== annotationId) { const annotation = this.annotationFacade.getAnnotationById(annotationId); if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsObject3D)(annotation)) return; this.annotationId = annotationId; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(this.offset, annotation.position[0] - cursorWorld[0], annotation.position[1] - cursorWorld[1], annotation.position[2] - cursorWorld[2]); this.lastFrameTime = performance.now(); } gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(this.target, cursorWorld[0], cursorWorld[1], cursorWorld[2]); this.hasTarget = true; this.ensureLoop(); } /** Commits the final 1:1 position (if the model still exists). */ end() { if (this.annotationId && this.hasTarget) { this.updateAnnotation(this.target); } if (this.rafId !== undefined) cancelAnimationFrame(this.rafId); this.rafId = undefined; this.annotationId = undefined; this.hasTarget = false; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(this.offset, 0, 0, 0); } ensureLoop() { if (this.rafId === undefined) { this.rafId = requestAnimationFrame(this.tick); } } tick = now => { this.rafId = undefined; if (!this.annotationId || !this.hasTarget) return; const dt = Math.max(0, now - this.lastFrameTime); this.lastFrameTime = now; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(this.offset, this.offset, Math.exp(-dt / FOLLOW_TAU_MS)); const settled = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(this.offset) < OFFSET_EPSILON; if (settled) gl_matrix__WEBPACK_IMPORTED_MODULE_0__.set(this.offset, 0, 0, 0); if (!this.updateAnnotation(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), this.target, this.offset))) { this.end(); return; } if (!settled) this.ensureLoop(); }; /** Writes `pos` to the tracked annotation. Returns false if it vanished. */ updateAnnotation(pos) { const annotation = this.annotationId ? this.annotationFacade.getAnnotationById(this.annotationId) : undefined; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsObject3D)(annotation)) return false; this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_2__.move)(annotation, [pos[0], pos[1], pos[2]])); return true; } } /***/ }, /***/ 50892 /*!***************************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/object3d-rotation-interaction.ts ***! \***************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3DRotationInteraction: () => (/* binding */ Object3DRotationInteraction) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** A full screen sweep rotates PI * ROTATION_SENSITIVITY (≈270° at 1.5). */ const ROTATION_SENSITIVITY = 1.5; /** * Rotates a selected Object3D in place via right-mouse drag, mapping * screen-space deltas to yaw/pitch about the camera's view-up and right axes. */ class Object3DRotationInteraction { annotationFacade; renderingEngineService; renderSettingsStore; object3DGeometryFacade; _isRotating = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "_isRotating" }] : [])); isRotating = this._isRotating.asReadonly(); dragState; /** * The single selected Object3D, or `undefined` if there isn't exactly one or it is locked. */ selectedObject3D = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const selected = this.annotationFacade.selectedAnnotations(); if (selected.length !== 1) return; const [first] = selected; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsObject3D)(first) || first.locked) return; return first; }, ...(ngDevMode ? [{ debugName: "selectedObject3D" }] : [])); constructor(annotationFacade, renderingEngineService, renderSettingsStore, object3DGeometryFacade) { this.annotationFacade = annotationFacade; this.renderingEngineService = renderingEngineService; this.renderSettingsStore = renderSettingsStore; this.object3DGeometryFacade = object3DGeometryFacade; } get isDragging() { return this.dragState !== undefined; } /** * Begin a right-mouse rotation drag if an Object3D is selected and the viewport's * camera/canvas are in a state that lets us derive rotation axes. * Returns `true` iff the drag was started. */ tryStartDrag(event, viewportId) { const selected = this.selectedObject3D(); if (!selected) return false; const screenPos = [event.offsetX, event.offsetY]; if (!this.clickIsInsideModel(selected, viewportId, screenPos)) return false; const axes = this.getRotationAxes(viewportId, event.currentTarget); if (!axes) return false; this.dragState = { annotationId: selected.id, axes, lastScreen: screenPos, viewportId }; this.renderSettingsStore.setLowQuality(true); return true; } /** * Apply a drag delta if the move is in the drag's origin viewport. * Returns `true` if the event was consumed by rotation. */ updateDrag(event, viewportId) { const drag = this.dragState; if (!drag || drag.viewportId !== viewportId) return false; // Per-frame screen-space delta in pixels. Updating `lastScreen` each call is what makes // rotations accumulate: the next event's dx/dy is applied on top of the orientation // produced by this frame, so the object appears to follow the cursor across a long drag. // If we kept the mousedown origin as the anchor instead, the rotation would snap back // toward identity whenever the cursor crossed the origin. const dx = event.offsetX - drag.lastScreen[0]; const dy = event.offsetY - drag.lastScreen[1]; drag.lastScreen = [event.offsetX, event.offsetY]; if (dx === 0 && dy === 0) return true; const annotation = this.annotationFacade.getAnnotationById(drag.annotationId); if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.annotationIsObject3D)(annotation)) return true; this._isRotating.set(true); this.applyYawPitch(annotation, drag.axes, dx, dy); return true; } endDrag() { if (!this.dragState) return; this.dragState = undefined; this.renderSettingsStore.setLowQuality(false); this._isRotating.set(false); } /** Cancel all in-flight rotation state. */ cancel() { const wasActive = this.dragState !== undefined || this._isRotating(); this.dragState = undefined; this._isRotating.set(false); if (wasActive) this.renderSettingsStore.setLowQuality(false); } applyYawPitch(annotation, axes, dx, dy) { // Horizontal drag (dx) → yaw around the camera's up axis. // Vertical drag (dy) → pitch around the camera's right axis. // Both axes are world-space. `rotateAboutAxis` pre-multiplies, so the composition is // final = pitch * yaw * current // Reading right-to-left: apply current, then yaw, then pitch. const yaw = this.angle(dx, axes.width); const pitch = this.angle(dy, axes.height); const rotated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.rotateAboutAxis)((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.rotateAboutAxis)(annotation, axes.up, yaw), axes.right, pitch); this.annotationFacade.updateAnnotation(rotated); } angle(delta, length) { // Map pixel displacement to radians. `delta / length` [-1, 1] is the signed fraction of // the canvas swept, multiplying by π gives 180° for a full-canvas sweep, and the // sensitivity factor stretches that to ~270° at the default ROTATION_SENSITIVITY. return delta / length * Math.PI * ROTATION_SENSITIVITY; } clickIsInsideModel(annotation, viewportId, screenPos) { const geometry = this.object3DGeometryFacade.getGeometry(annotation.id); const shell = geometry?.shell; if (!shell) return false; const userMatrix = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.buildObject3dTransform)(annotation, geometry.centroid); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.silhouetteContainsClick)(shell, userMatrix, world => this.renderingEngineService.worldToCanvas(viewportId, [world[0], world[1], world[2]]), screenPos); } getRotationAxes(viewportId, target) { const camera = this.renderingEngineService.getViewport(viewportId)?.getCamera?.(); if (!camera?.viewUp || !camera.viewPlaneNormal) return undefined; const canvas = target instanceof HTMLElement ? target : undefined; const width = canvas?.clientWidth ?? 0; const height = canvas?.clientHeight ?? 0; if (width <= 0 || height <= 0) return undefined; const up = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.fromValues(camera.viewUp[0], camera.viewUp[1], camera.viewUp[2]); const normal = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.fromValues(camera.viewPlaneNormal[0], camera.viewPlaneNormal[1], camera.viewPlaneNormal[2]); const right = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), up, normal); return { height, right, up, width }; } } /***/ }, /***/ 64974 /*!*************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/pan-interaction.ts ***! \*************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PanInteraction: () => (/* binding */ PanInteraction) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Handles panning by moving the isocenter relative to mouse movement. */ class PanInteraction { renderingEngineService; viewportStore; panPosition; constructor(renderingEngineService, viewportStore) { this.renderingEngineService = renderingEngineService; this.viewportStore = viewportStore; } get isActive() { return this.panPosition !== undefined; } start(mousePos) { this.panPosition = { cursor2D: mousePos, isocenter: this.viewportStore.isocenter() }; } update(mousePos, viewportId) { if (this.panPosition === undefined) return; const currentPosition = this.renderingEngineService.getWorldPosition(viewportId, mousePos); // Instead of storing the last 3d cursor position, we calculate it now // from the last 2d position to account for camera changes etc. const previousPosition = this.renderingEngineService.getWorldPosition(viewportId, this.panPosition.cursor2D); if (!currentPosition || !previousPosition) return; const delta = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), currentPosition, previousPosition); const newIsocenter = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), this.panPosition.isocenter, delta); this.panPosition = { cursor2D: mousePos, isocenter: newIsocenter }; this.viewportStore.updateIsoCenter((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.position)(newIsocenter[0], newIsocenter[1], newIsocenter[2])); } end() { this.panPosition = undefined; } } /***/ }, /***/ 22526 /*!****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/scroll-interaction.ts ***! \****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ScrollInteraction: () => (/* binding */ ScrollInteraction) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** * Scrolls through volume slices by moving the intersection * along the view normal of the viewport scrolled on. */ class ScrollInteraction { renderingEngineService; viewportStore; constructor(renderingEngineService, viewportStore) { this.renderingEngineService = renderingEngineService; this.viewportStore = viewportStore; } update(delta, viewportId) { const viewport = this.renderingEngineService.getViewport(viewportId); const viewNormal = viewport?.getCamera().viewPlaneNormal; if (!viewNormal) return; const intersection = this.viewportStore.intersection(); const updated = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), intersection, viewNormal, delta); this.viewportStore.updateIntersection(updated); } } /***/ }, /***/ 66646 /*!***************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/twist-interaction.ts ***! \***************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TwistInteraction: () => (/* binding */ TwistInteraction) /* harmony export */ }); /** * Rotates the slice plane about its view normal at the given viewport. */ class TwistInteraction { viewportStore; constructor(viewportStore) { this.viewportStore = viewportStore; } update(deltaDegrees, viewportId) { const axis = this.viewportStore.viewportAxisMapping()[viewportId]; if (!axis) return; this.viewportStore.rotateCrosshair(axis, deltaDegrees); } } /***/ }, /***/ 78730 /*!***********************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/wheel-quality-interaction.ts ***! \***********************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WheelQualityInteraction: () => (/* binding */ WheelQualityInteraction) /* harmony export */ }); class WheelQualityInteraction { renderSettingsStore; timeoutMs; constructor(renderSettingsStore, timeoutMs = 200) { this.renderSettingsStore = renderSettingsStore; this.timeoutMs = timeoutMs; } start() { this.renderSettingsStore.lowQualityWithTimeout(this.timeoutMs); } } /***/ }, /***/ 76371 /*!*************************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/window-settings-interaction.ts ***! \*************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WindowSettingsInteraction: () => (/* binding */ WindowSettingsInteraction) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 50600); /* harmony import */ var _cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core/utilities */ 67966); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Updated the window level/width values for MPR viewports * relative to mouse movements */ class WindowSettingsInteraction { renderingEngineService; renderSettingsStore; prevPosition; get isActive() { return this.prevPosition !== undefined; } constructor(renderingEngineService, renderSettingsStore) { this.renderingEngineService = renderingEngineService; this.renderSettingsStore = renderSettingsStore; } start(mousePos) { this.prevPosition = mousePos; } update(mousePos, viewportId) { if (this.prevPosition === undefined) return; const deltas = [mousePos[0] - this.prevPosition[0], mousePos[1] - this.prevPosition[1]]; if (viewportId === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportAxisState.RIGHTMAIN) { this.update3d(deltas); } else { this.updateMPR(deltas); } this.prevPosition = mousePos; } updateMPR(deltas) { const currentSettings = this.renderSettingsStore.windowSettings(); const update = { level: currentSettings.level + deltas[0], width: currentSettings.width + deltas[1] }; const viewport = this.renderingEngineService.getViewport(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportAxisState.TOPLEFTMAIN); if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"]) { const [scalarMin, scalarMax] = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.getVolumeScalarRange)(viewport); const windowWidthMax = Math.max(1, (scalarMax - scalarMin) * 2); const windowWidthMin = 1; update.level = (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(update.level, scalarMin, scalarMax); update.width = (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(update.width, windowWidthMin, windowWidthMax); } this.renderSettingsStore.updateCustomPreset(update); } update3d(deltas) { const preset = this.renderSettingsStore.volumeSettings(); if (preset.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.VolumeRenderingOption.ENDO || preset.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.VolumeRenderingOption.VASCULAR) { return; } const viewport = this.renderingEngineService.getViewport(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportAxisState.RIGHTMAIN); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"])) return; if (preset.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.VolumeRenderingOption.MIP) { this.updateMipWindow(preset, deltas, viewport); return; } const [brightnessMin, brightnessMax] = [-1, 1.5]; const [thresholdMin, thresholdMax] = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.getVolumeScalarRange)(viewport); // Brightness has a smaller range so we divide the delta const [brightnessDelta, thresholdDelta] = [deltas[0] / 200, deltas[1]]; const update = { ...preset, brightness: (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(preset.brightness + brightnessDelta, brightnessMin, brightnessMax), threshold: (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(preset.threshold + thresholdDelta, thresholdMin, thresholdMax) }; this.renderSettingsStore.updateVolumeSettings(update); } /** MIP is just a projected HU image, so drag-to-adjust follows the same width/level * convention as updateMPR above (no /200 brightness scaling, real-HU bounds), even though it * reuses fluoro/xray's brightness/threshold field names - brightness is the window level, * threshold is the window width. */ updateMipWindow(preset, deltas, viewport) { const [scalarMin, scalarMax] = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.getVolumeScalarRange)(viewport); const windowWidthMax = Math.max(1, (scalarMax - scalarMin) * 2); const update = { ...preset, brightness: (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(preset.brightness + deltas[0], scalarMin, scalarMax), threshold: (0,_cornerstonejs_core_utilities__WEBPACK_IMPORTED_MODULE_1__["default"])(preset.threshold + deltas[1], 1, windowWidthMax) }; this.renderSettingsStore.updateVolumeSettings(update); } end() { this.prevPosition = undefined; } } /***/ }, /***/ 82908 /*!**************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/interactions/zoom-interaction.ts ***! \**************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ZoomInteraction: () => (/* binding */ ZoomInteraction) /* harmony export */ }); const MIN_ZOOM = 0.1; const MAX_ZOOM = 10; /** * Updates viewport's zoom values based on the provided delta */ class ZoomInteraction { viewportStore; constructor(viewportStore) { this.viewportStore = viewportStore; } update(delta) { const zoom = this.viewportStore.zoom(); const next = zoom * Math.exp(delta / 2000); this.viewportStore.updateZoom(Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, next))); } } /***/ }, /***/ 92192 /*!******************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/object3d-shell-picker.ts ***! \******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3dShellPicker: () => (/* binding */ Object3dShellPicker) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /** * Ranks the Object3D shells under a screen point, best candidate first. * * The shell is the solid picking proxy (a filled cylinder for HollowCylinder, * the convex hull for STL), so a ray that passes through a hole still resolves * to the model. Shared by click-selection and hover so the two always agree on * what is under the cursor. The silhouette test fast-rejects via the projected * AABB before touching every vertex, so calling this on every hover frame is * cheap unless the cursor is actually over a model. */ class Object3dShellPicker { annotationFacade; renderingEngineService; object3DGeometryFacade; constructor(annotationFacade, renderingEngineService, object3DGeometryFacade) { this.annotationFacade = annotationFacade; this.renderingEngineService = renderingEngineService; this.object3DGeometryFacade = object3DGeometryFacade; } /** Annotation ids of every shell the screen point hits, best candidate first. */ pickShellAnnotationIds(viewportId, screenPos) { const ray = this.renderingEngineService.getWorldRay(viewportId, screenPos); if (!ray) return []; const candidates = this.getShellHits(viewportId, screenPos, ray); this.sortShellCandidates(candidates); return candidates.map(candidate => candidate.annotationId); } /** * One candidate per Object3D shell whose silhouette covers the cursor. MPR * viewports carry extra ranking fields, 3D viewports rank on depth alone. */ getShellHits(viewportId, screenPos, ray) { const sliceRange = this.renderingEngineService.getSliceTRange(viewportId); const slabAxes = sliceRange ? this.renderingEngineService.cameraSlabPlaneAxes(viewportId) : undefined; if (sliceRange && !slabAxes) return []; const project = world => this.renderingEngineService.worldToCanvas(viewportId, [world[0], world[1], world[2]]); const candidates = []; for (const annotation of this.annotationFacade.annotations()) { if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationIsObject3D)(annotation) || annotation.hidden) continue; const geometry = this.object3DGeometryFacade.getGeometry(annotation.id); const shell = geometry?.shell; if (!shell) continue; const userMatrix = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.buildObject3dTransform)(annotation, geometry.centroid); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.silhouetteContainsClick)(shell, userMatrix, project, screenPos)) continue; const tEnter = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.aabbCentreDepth)(shell.bounds, userMatrix, ray); candidates.push(slabAxes ? { annotationId: annotation.id, area2d: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.projectedAabbArea)(shell.bounds, userMatrix, slabAxes), kind: 'mpr', tEnter, volume3d: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.aabbVolume)(shell.bounds) } : { annotationId: annotation.id, kind: 'volume3d', tEnter }); } return candidates; } /** Sorts in place. MPR ranks on smallest projected 2D AABB, then smaller 3D volume. */ sortShellCandidates(candidates) { if (candidates[0]?.kind === 'mpr') { candidates.sort((a, b) => a.area2d - b.area2d || a.volume3d - b.volume3d); } else { candidates.sort((a, b) => b.tEnter - a.tEnter); } } } /***/ }, /***/ 46184 /*!*************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-interaction/viewport-interaction.service.ts ***! \*************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportInteractionService: () => (/* binding */ ViewportInteractionService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 33242); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _colors_colors_service__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../colors/colors.service */ 39298); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../viewport-ids */ 85309); /* harmony import */ var _interactions_annotation_create_interaction__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./interactions/annotation-create-interaction */ 34837); /* harmony import */ var _interactions_annotation_select_interaction__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./interactions/annotation-select-interaction */ 59821); /* harmony import */ var _interactions_hover_interaction__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./interactions/hover-interaction */ 50295); /* harmony import */ var _interactions_object3d_drag_interaction__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./interactions/object3d-drag-interaction */ 38112); /* harmony import */ var _interactions_object3d_rotation_interaction__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./interactions/object3d-rotation-interaction */ 50892); /* harmony import */ var _interactions_pan_interaction__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./interactions/pan-interaction */ 64974); /* harmony import */ var _interactions_scroll_interaction__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./interactions/scroll-interaction */ 22526); /* harmony import */ var _interactions_twist_interaction__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./interactions/twist-interaction */ 66646); /* harmony import */ var _interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./interactions/wheel-quality-interaction */ 78730); /* harmony import */ var _interactions_window_settings_interaction__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./interactions/window-settings-interaction */ 76371); /* harmony import */ var _interactions_zoom_interaction__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./interactions/zoom-interaction */ 82908); /* harmony import */ var _object3d_shell_picker__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./object3d-shell-picker */ 92192); // 2x the default pick tolerance (see RenderingEngineService.getScreenPositionActor) - // mirrors AnnotationCreateInteraction's FIRST_POINT_HIT_RADIUS for the click-to-close // check, so hovering and clicking agree on what counts as "on" the first point. const FIRST_POINT_HIT_RADIUS = 10; const LEFT_MOUSE_BUTTON = 0; const MIDDLE_MOUSE_BUTTON = 1; const RIGHT_MOUSE_BUTTON = 2; /** Maps `MouseEvent.button` values to the corresponding `MouseEvent.buttons` bitmask. */ const BUTTONS_BITMASK = { [LEFT_MOUSE_BUTTON]: 1, [MIDDLE_MOUSE_BUTTON]: 4, [RIGHT_MOUSE_BUTTON]: 2 }; class ViewportInteractionService { annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.AnnotationFacade); colorsService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_colors_colors_service__WEBPACK_IMPORTED_MODULE_11__.ColorsService); interactionModeService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_12__.InteractionModeService); renderingEngineService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_4__.RenderingEngineService); contextMenuSubject = new rxjs__WEBPACK_IMPORTED_MODULE_2__.Subject(); renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.renderSettingsStore); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.viewportStore); volumeViewerStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.volumeViewerStore); object3DGeometryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_8__.Object3DGeometryFacade); // Interactions annotationCreate = new _interactions_annotation_create_interaction__WEBPACK_IMPORTED_MODULE_14__.AnnotationCreateInteraction(this.annotationFacade, this.colorsService, this.renderingEngineService, this.viewportStore); object3dShellPicker = new _object3d_shell_picker__WEBPACK_IMPORTED_MODULE_25__.Object3dShellPicker(this.annotationFacade, this.renderingEngineService, this.object3DGeometryFacade); annotationSelect = new _interactions_annotation_select_interaction__WEBPACK_IMPORTED_MODULE_15__.AnnotationSelectInteraction(this.annotationFacade, this.renderingEngineService, this.viewportStore, this.object3dShellPicker); hover = new _interactions_hover_interaction__WEBPACK_IMPORTED_MODULE_16__.HoverInteraction(this.renderingEngineService, this.object3dShellPicker); object3DRotation = new _interactions_object3d_rotation_interaction__WEBPACK_IMPORTED_MODULE_18__.Object3DRotationInteraction(this.annotationFacade, this.renderingEngineService, this.renderSettingsStore, this.object3DGeometryFacade); object3DDrag = new _interactions_object3d_drag_interaction__WEBPACK_IMPORTED_MODULE_17__.Object3DDragInteraction(this.annotationFacade); scroll = new _interactions_scroll_interaction__WEBPACK_IMPORTED_MODULE_20__.ScrollInteraction(this.renderingEngineService, this.viewportStore); pan = new _interactions_pan_interaction__WEBPACK_IMPORTED_MODULE_19__.PanInteraction(this.renderingEngineService, this.viewportStore); twist = new _interactions_twist_interaction__WEBPACK_IMPORTED_MODULE_21__.TwistInteraction(this.viewportStore); wheelQuality = new _interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_22__.WheelQualityInteraction(this.renderSettingsStore); windowSettings = new _interactions_window_settings_interaction__WEBPACK_IMPORTED_MODULE_23__.WindowSettingsInteraction(this.renderingEngineService, this.renderSettingsStore); zoom = new _interactions_zoom_interaction__WEBPACK_IMPORTED_MODULE_24__.ZoomInteraction(this.viewportStore); constructor() { // Electron-only macOS trackpad twist. const onTrackpadRotate = globalThis.electronAPI?.onTrackpadRotate; if (!onTrackpadRotate) return; const unsubscribe = onTrackpadRotate(({ clientX, clientY, rotation }) => { const viewportId = this.viewportAtPoint(clientX, clientY); if (viewportId) this.twist.update(rotation, viewportId); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(unsubscribe); } viewportAtPoint(clientX, clientY) { for (const [id, vp] of Object.entries(this.volumeViewerStore.registeredViewports())) { const element = vp.element; if (!element) continue; const rect = element.getBoundingClientRect(); if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) { return id; } } return undefined; } /** Enter-to-finish for annotation creation (splines) - see AnnotationCreateInteraction.completeIfValid. * Only trusts the tracked mouse position when the pointer is currently over the same * viewport the spline is being created in - otherwise it's either the untouched [0, 0, 0] * default (no mousemove yet) or a stale position from a different viewport, so completion * falls back to the already-confirmed points instead of appending a bogus one. */ completeAnnotationCreationIfValid(annotation) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(annotation)) { // Mirrors the click path's closure rule (splineBeingCreated/isFirstPointHit): if the // hover-preview already shows the loop closing on the first point, finish with the // existing points instead of appending a near-duplicate point next to point 0. const hovered = this._hoveredAnnotation(); const closingFirstPoint = annotation.points.length > 1 && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsClosedSpline)(annotation) && hovered?.annotationId === annotation.id && hovered.pointIndex === 0; if (closingFirstPoint) { this.annotationCreate.completeIfValid(annotation); return; } const worldPos = this.mouseMoveViewportId === this.creationViewportId ? this._mouseWorldPosition() : undefined; if (worldPos) { this.annotationCreate.completeSplineWithCurrentPosition(annotation, worldPos); } else { this.annotationCreate.completeIfValid(annotation); } return; } this.annotationCreate.completeIfValid(annotation); } /** Only relevant while creating a closed spline - see HoverInteraction.handle's * expandedFirstPointCheck for why this needs a wider radius than the flat default. */ closedSplineFirstPointHoverCheck() { const interactionMode = this.interactionModeService.interactionMode(); if (interactionMode.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.InteractionModeType.CREATE) return undefined; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsClosedSpline)(interactionMode.annotation)) return undefined; return { annotationId: interactionMode.annotation.id, hitRadius: FIRST_POINT_HIT_RADIUS }; } openContextMenu$ = this.contextMenuSubject.asObservable(); lastClick; currentScreenPos = [0, 0]; _mouseWorldPosition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([0, 0, 0], ...(ngDevMode ? [{ debugName: "_mouseWorldPosition" }] : [])); get mouseWorldPosition() { return this._mouseWorldPosition; } _hoveredAnnotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(undefined, { ...(ngDevMode ? { debugName: "_hoveredAnnotation" } : {}), // Adding equality function so that we don't send out unnecessary updates // if the same value is found over multiple mousemove events equal: (a, b) => a?.annotationId === b?.annotationId && a?.pointIndex === b?.pointIndex }); get hoveredAnnotation() { return this._hoveredAnnotation; } _dragDetails = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)({}, ...(ngDevMode ? [{ debugName: "_dragDetails" }] : [])); dragDetails = this._dragDetails; /** * Cursor style for the viewport based on interaction state */ viewportCursor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { if (this.object3DRotation.isRotating()) return 'all-scroll'; const dragId = this._dragDetails().annotationId; if (dragId) { const dragged = this.annotationFacade.getAnnotationById(dragId); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsObject3D)(dragged) && !dragged.locked) return 'grabbing'; } const hovered = this._hoveredAnnotation(); if (hovered?.annotationId) { const annotation = this.annotationFacade.getAnnotationById(hovered.annotationId); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsObject3D)(annotation) && !annotation.locked) return 'grab'; } return ''; }, ...(ngDevMode ? [{ debugName: "viewportCursor" }] : [])); get draggingId() { return this._dragDetails().annotationId; } get draggingIndex() { return this._dragDetails().pointIndex; } mousedownViewportId; mouseMoveViewportId; creationViewportId; mousedownButton; rightMousedownViewportId; rightDragMoved = false; suppressNextContextMenu = false; lastGestureRotation = 0; lastGestureScale = 1; pendingGestureRotation = 0; pendingGestureScale = 1; gestureViewportId; gestureFrame; gestureActive = false; /** * Handles viewport click events and determines interaction type. * Should be called on mousedown to capture click position and detect double-clicks. * * @returns Object containing click info and whether it was a double-click */ handleViewportMouseDown(event, viewportId) { const screenPos = [event.offsetX, event.offsetY]; this.mousedownViewportId = viewportId; this.mousedownButton = event.button; // Clear any stale suppression from a previous gesture. // // Example: A right-drag sets `suppressNextContextMenu` on mouseup, but on macOS // the `contextmenu` event fires on mousedown (before that mouseup), so the flag it meant // to suppress has already passed, leaving it stranded `true` and wrongly suppressing the // NEXT gesture's context menu. mousedown fires before contextmenu, so resetting // here lands before this gesture's menu is evaluated. this.suppressNextContextMenu = false; // Right-click (camera rotate/pan) always affects the 3D volume render. // Left-click in AXIAL/SAGITTAL moves the crosshair which causes the 3D viewport to re-render. // Left-click in REFORMAT/CORONAL only changes the crosshair position without re-rendering // the 3D volume itself, so those are excluded. const leftClickAffects3d = event.button === LEFT_MOUSE_BUTTON && !_viewport_ids__WEBPACK_IMPORTED_MODULE_13__.NON_DEGRADING_VIEWPORT_ID_LIST.includes(viewportId); if (event.button === RIGHT_MOUSE_BUTTON || leftClickAffects3d) { this.renderSettingsStore.setLowQuality(true); } if (event.button === RIGHT_MOUSE_BUTTON) { this.rightMousedownViewportId = viewportId; this.rightDragMoved = false; if (event.ctrlKey) { this.windowSettings.start(screenPos); return; } if (!this.object3DRotation.tryStartDrag(event, viewportId)) { this.pan.start(screenPos); } return; } if (event.button !== LEFT_MOUSE_BUTTON) return undefined; const currentClick = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.clickInfo)(event); const previousClick = this.lastClick; const wasDoubleClick = !!previousClick && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.isDoubleClick)(previousClick, currentClick); this.lastClick = currentClick; this.currentScreenPos = screenPos; return { isDoubleClick: wasDoubleClick }; } /** * The volume was clicked while in creation mode */ handleAnnotationCreationClick(viewportId, annotationBeingCreated, isDoubleClick) { this.creationViewportId = viewportId; const details = this.annotationCreate.handle(this.currentScreenPos, viewportId, annotationBeingCreated, isDoubleClick); if (details) { this._dragDetails.set(details); } } handleAddPointClick(viewportId, annotationId, isDoubleClick) { if (isDoubleClick) { this.interactionModeService.clearMode(); return; } const worldPos = this.renderingEngineService.getWorldPosition(viewportId, this.currentScreenPos); if (!worldPos) { return; } const annotation = this.annotationFacade.getAnnotationById(annotationId); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsSpline)(annotation)) { // If already hovering on an existing point, don't add new one - // instead drag that existing point const hovered = this._hoveredAnnotation(); if (hovered?.annotationId === annotation.id && hovered.pointIndex !== undefined) { this.handleAnnotationSelectionClick(viewportId, false); return; } const path = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_7__.getSplinePath)(annotation); const snappedPos = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.snapPositionToSpline)(worldPos, path); const { addedAt, points } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_10__.addPointToSpline)(annotation.points, path, snappedPos); this.annotationFacade.updateAnnotation({ ...annotation, points }); // Only drag newly created point if actually touching it if (gl_matrix__WEBPACK_IMPORTED_MODULE_3__.distance(snappedPos, worldPos) < 3) { this._dragDetails.set({ annotationId, pointIndex: addedAt }); } } } /** An actor or the volume was clicked while not in creation mode. */ handleAnnotationSelectionClick(viewportId, multiselect = false) { const previouslySelected = new Set(this.annotationFacade.selectedIds()); const details = this.annotationSelect.handle(this.currentScreenPos, viewportId, multiselect); if (!details) return undefined; // Object3D needs a second mousedown before drag arms, and locked objects // never arm. Both conditions apply only to Object3D annotations. const annotation = this.annotationFacade.getAnnotationById(details.annotationId); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsObject3D)(annotation) && (annotation.locked || !previouslySelected.has(details.annotationId))) return details; this._dragDetails.set(details); return details; } /** * W/L drag for the CPR carriers: they are bare mounts with no `lib-volume-viewport` to * route through, and the full mouse-move path would hit-test annotations they exclude. */ startWindowSettingsDrag(screenPos) { this.windowSettings.start(screenPos); } updateWindowSettingsDrag(screenPos, viewportId) { if (this.windowSettings.isActive) this.windowSettings.update(screenPos, viewportId); } handleViewportMouseMove(event, viewportId) { if (this.cancelledPhantomButton(event)) return; const screenPos = [event.offsetX, event.offsetY]; if (this.handleActiveInteractionMove(screenPos, viewportId)) return; if (this.object3DRotation.updateDrag(event, viewportId)) return; const worldPos = this.renderingEngineService.getWorldPosition(viewportId, screenPos); if (!worldPos) return; this._mouseWorldPosition.set(worldPos); this.mouseMoveViewportId = viewportId; // Crosshair is only moved by a left-button drag in its origin viewport. if (this.mousedownViewportId === viewportId && this.mousedownButton === LEFT_MOUSE_BUTTON) { this.setCrosshairPos(worldPos); } const draggingId = this.draggingId; if (!draggingId) { // We only need to worry about hovers if we're not dragging something this.hover.handle([event.offsetX, event.offsetY], viewportId, this._hoveredAnnotation, this.closedSplineFirstPointHoverCheck()); return; } if (this.mousedownViewportId !== viewportId || this.mousedownButton !== LEFT_MOUSE_BUTTON) { return; } this.handleDragMove(draggingId, worldPos); } handleActiveInteractionMove(screenPos, viewportId) { if (this.pan.isActive) { if (this.mousedownViewportId === viewportId) this.pan.update(screenPos, viewportId); return true; } if (this.windowSettings.isActive) { if (this.mousedownViewportId === viewportId) this.windowSettings.update(screenPos, viewportId); return true; } return false; } handleDragMove(draggingId, worldPos) { const beingCreated = this.annotationFacade.annotationBeingCreated(); const toUpdate = this.annotationFacade.getAnnotationById(draggingId) ?? (beingCreated?.id === draggingId ? beingCreated : undefined); if (!toUpdate) { this._dragDetails.set({}); return; } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationHasPoints)(toUpdate) && this.draggingIndex !== undefined) { this.updatePoints(toUpdate, this.draggingIndex, worldPos, beingCreated); } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsObject3D)(toUpdate)) { this.object3DDrag.update(toUpdate.id, [...worldPos]); return; } if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationHasPosition)(toUpdate)) { this.annotationFacade.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_9__.move)(toUpdate, [...worldPos])); } } updatePoints(toUpdate, index, worldPos, beingCreated) { if (toUpdate.points[index]) { const update = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_9__.movePoint)(toUpdate, index, [...worldPos]); if (toUpdate === beingCreated) { this.annotationFacade.creatingAnnotation(update); } else { this.annotationFacade.updateAnnotation(update); } } } handleContextMenu(outputEvent, viewportId) { if (outputEvent.key) { this.contextMenuSubject.next(`${viewportId}:${outputEvent.key}`); return; } if (this.suppressNextContextMenu) { this.suppressNextContextMenu = false; return; } const event = outputEvent.event; const screenPos = [event.offsetX, event.offsetY]; const actor = this.renderingEngineService.getScreenPositionActor(viewportId, screenPos); if (actor) { // Update context menu items const { annotationId, pointIndex } = this.getActorAnnotationDetails(actor) ?? {}; if (annotationId) { if (pointIndex === undefined) { this.contextMenuSubject.next(annotationId); } else { this.contextMenuSubject.next(`${annotationId}:${pointIndex}`); } return; } } // Open viewport-specific menu this.openViewportMenu(); } openViewportMenu() { this.contextMenuSubject.next('viewport'); } handleMouseUp() { const rightClickLostOrigin = this.mousedownButton === RIGHT_MOUSE_BUTTON && this.rightMousedownViewportId === undefined; const shouldOpenContextMenu = this.mousedownButton === RIGHT_MOUSE_BUTTON && !this.rightDragMoved && !rightClickLostOrigin; if (!shouldOpenContextMenu && this.mousedownButton === RIGHT_MOUSE_BUTTON) { this.suppressNextContextMenu = true; } this.resetAllInteractions(); return { shouldOpenContextMenu }; } /** * Cancels all in-flight interactions without emitting a context-menu signal. * Used on `window:blur`, where no `mouseup` will fire. */ cancelInteractions() { this.discardPendingGesture(); this.resetAllInteractions(); } /** * When wee still believe a button is pressed, but the OS-reported buttons bitmask says otherwise. * Must be bound to `window:mousemove` so we also catch re-entry outside the viewport. * Returns `true` if a phantom-press was found and interactions were cancelled */ handleGlobalMouseMove(event) { if (this.mousedownButton === RIGHT_MOUSE_BUTTON) { this.rightDragMoved = true; } this.cancelledPhantomButton(event); } cancelledPhantomButton(event) { if (this.mousedownButton === undefined) return false; const bit = BUTTONS_BITMASK[this.mousedownButton]; // eslint-disable-next-line sonarjs/bitwise-operators -- event.buttons is a genuine bitmask if (bit === undefined || (event.buttons & bit) !== 0) return false; this.cancelInteractions(); return true; } resetAllInteractions() { const wasInteracting = this.mousedownButton !== undefined; this.pan.end(); this.windowSettings.end(); this.object3DRotation.cancel(); this.object3DDrag.end(); this._dragDetails.set({}); this.mousedownButton = undefined; this.rightMousedownViewportId = undefined; this.mousedownViewportId = undefined; if (wasInteracting) { this.renderSettingsStore.setLowQuality(false); } } setCrosshairPos(pos) { this.viewportStore.updateIntersection(pos); } getActorAnnotationDetails(actor) { const properties = actor?.get('annotationId', 'pointIndex'); if (properties?.annotationId === undefined) { return; } return properties; } handleWheel(event, viewportId) { // Suppress default to avoid triggering full-page zoom. event.preventDefault(); this.wheelQuality.start(); // Pinch gestures on a touchpad are reported as wheel events with ctrlKey set. // macOS reports pinch-out as negative deltaY and pinch-in as positive. // Consumed without dispatch while a Safari GestureEvent is in flight, so // double-handling doesn't zoom twice and fall-through doesn't scroll slices. if (event.ctrlKey) { if (this.gestureActive) return; // Native expectation is pinch-out → zoom in, so we negate. const delta = event.deltaMode === WheelEvent.DOM_DELTA_PIXEL ? -event.deltaY * 7 : -Math.sign(event.deltaY) * 500; this.zoom.update(delta); return; } // Shift+wheel rotates the slice plane about its view normal. if (event.shiftKey) { // Browsers translate Shift+wheel on a mouse to horizontal scroll, // so fall back to deltaX when deltaY is zero. const rawDelta = event.deltaY === 0 ? event.deltaX : event.deltaY; const delta = event.deltaMode === WheelEvent.DOM_DELTA_PIXEL ? rawDelta * 0.0375 : Math.sign(rawDelta) * 0.15; this.twist.update(delta, viewportId); return; } const scrollDelta = event.deltaMode === WheelEvent.DOM_DELTA_PIXEL ? event.deltaY * 0.0075 : Math.sign(event.deltaY) * 1; this.scroll.update(scrollDelta, viewportId); } /** * Safari trackpad gesture (twist + pinch). Dispatches are coalesced to one per * animation frame; a fixed-interval throttle aliases against the ~60Hz * gesturechange stream and stutters. */ handleGestureStart(event) { const gesture = event; this.lastGestureRotation = gesture.rotation; this.lastGestureScale = gesture.scale; this.gestureActive = true; // Engage interaction LOD before the first dispatch, matching the wheel path. this.wheelQuality.start(); } handleGestureChange(event, viewportId) { const gesture = event; this.pendingGestureRotation = gesture.rotation; this.pendingGestureScale = gesture.scale; this.gestureViewportId = viewportId; if (this.gestureFrame !== undefined) return; this.gestureFrame = requestAnimationFrame(() => { this.gestureFrame = undefined; this.dispatchGestureDeltas(); }); } handleGestureEnd() { if (this.gestureFrame !== undefined) { cancelAnimationFrame(this.gestureFrame); this.gestureFrame = undefined; this.dispatchGestureDeltas(); } this.gestureActive = false; } // Unlike handleGestureEnd, cancellation must not flush the pending delta. discardPendingGesture() { if (this.gestureFrame !== undefined) { cancelAnimationFrame(this.gestureFrame); this.gestureFrame = undefined; } this.gestureActive = false; this.gestureViewportId = undefined; } dispatchGestureDeltas() { if (this.gestureViewportId === undefined) return; this.wheelQuality.start(); const deltaRotation = this.pendingGestureRotation - this.lastGestureRotation; const deltaScale = Math.log(this.lastGestureScale / this.pendingGestureScale); this.lastGestureRotation = this.pendingGestureRotation; this.lastGestureScale = this.pendingGestureScale; if (deltaRotation !== 0) this.twist.update(-deltaRotation, this.gestureViewportId); if (deltaScale !== 0) this.zoom.update(-deltaScale * 2000); } static ɵfac = function ViewportInteractionService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportInteractionService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ViewportInteractionService, factory: ViewportInteractionService.ɵfac }); } /***/ }, /***/ 86026 /*!**********************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-overlay/crosshair/crosshair.component.ts ***! \**********************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CrosshairComponent: () => (/* binding */ CrosshairComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewport-ids */ 85309); /* harmony import */ var _viewport_interaction_interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewport-interaction/interactions/wheel-quality-interaction */ 78730); /* harmony import */ var _window_details_window_details_service__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../window-details/window-details.service */ 99360); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/core */ 14975); /* eslint-disable @angular-eslint/component-selector */ const _c0 = ["lib-crosshair", ""]; function CrosshairComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](0, "line", 1)(1, "line", 1)(2, "line", 2)(3, "line", 2)(4, "circle", 3); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); const arm_r2 = ctx_r0.shortArmLength(); const shortGap_r3 = ctx_r0.shortArmGap(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", -arm_r2)("x2", -shortGap_r3)("stroke-width", ctx_r0.shortArmStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", shortGap_r3)("x2", arm_r2)("stroke-width", ctx_r0.shortArmStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.vColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", -arm_r2)("y2", -shortGap_r3)("stroke-width", ctx_r0.shortArmStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.vColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", shortGap_r3)("y2", arm_r2)("stroke-width", ctx_r0.shortArmStrokeWidth()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("fill", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("r", ctx_r0.centreDotRadius()); } } function CrosshairComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](0, "rect")(1, "line", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementStart"](2, "line", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomListener"]("mouseover", function CrosshairComponent_Conditional_2_Template_line_mouseover_2_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover("v")); })("mouseout", function CrosshairComponent_Conditional_2_Template_line_mouseout_2_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover(undefined)); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](3, "line", 2); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementStart"](4, "line", 4); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomListener"]("mouseover", function CrosshairComponent_Conditional_2_Template_line_mouseover_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover("v")); })("mouseout", function CrosshairComponent_Conditional_2_Template_line_mouseout_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover(undefined)); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](5, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementStart"](6, "line", 5); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomListener"]("mouseover", function CrosshairComponent_Conditional_2_Template_line_mouseover_6_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover("h")); })("mouseout", function CrosshairComponent_Conditional_2_Template_line_mouseout_6_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover(undefined)); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](7, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementStart"](8, "line", 5); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomListener"]("mouseover", function CrosshairComponent_Conditional_2_Template_line_mouseover_8_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover("h")); })("mouseout", function CrosshairComponent_Conditional_2_Template_line_mouseout_8_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r0.axisHover(undefined)); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElement"](9, "line", 1)(10, "line", 2); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵnextContext"](); const length_r5 = ctx_r0.lineLength(); const gap_r6 = ctx_r0.middleGap(); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x", -length_r5)("y", -length_r5)("width", length_r5 * 2)("height", length_r5 * 2)("fill", ctx_r0.rectFill()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.vColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", -length_r5)("y2", -gap_r6)("stroke-width", ctx_r0.vSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", -length_r5)("y2", -gap_r6 + ctx_r0.hitWidth() / 2)("stroke-width", ctx_r0.hitWidth())("stroke", "transparent"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.vColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", gap_r6)("y2", length_r5)("stroke-width", ctx_r0.vSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", gap_r6 - ctx_r0.hitWidth() / 2)("y2", length_r5)("stroke-width", ctx_r0.hitWidth())("stroke", "transparent"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", -length_r5)("x2", -gap_r6)("stroke-width", ctx_r0.hSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", -length_r5)("x2", -gap_r6 + ctx_r0.hitWidth() / 2)("stroke-width", ctx_r0.hitWidth())("stroke", "transparent"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("stroke", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", gap_r6)("x2", length_r5)("stroke-width", ctx_r0.hSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", gap_r6 - ctx_r0.hitWidth() / 2)("x2", length_r5)("stroke-width", ctx_r0.hitWidth())("stroke", "transparent"); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("opacity", 0.2)("stroke", ctx_r0.hColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("x1", -gap_r6)("x2", gap_r6)("stroke-width", ctx_r0.scaledSize()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵstyleProp"]("opacity", 0.2)("stroke", ctx_r0.vColor()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("y1", -gap_r6)("y2", gap_r6)("stroke-width", ctx_r0.scaledSize()); } } // The additional tolerance to add to the hit area outside of the visible line. const HIT_TOLERANCE_PX = 30; class CrosshairComponent { axis = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "axis" }] : [])); viewportId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "viewportId" }] : [])); position = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "position" }] : [])); rotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "rotation" }] : [])); size = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(2, ...(ngDevMode ? [{ debugName: "size" }] : [])); hColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('var(--p-app-viewport-axis-axial)', ...(ngDevMode ? [{ debugName: "hColor" }] : [])); vColor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('var(--p-app-viewport-axis-sagittal)', ...(ngDevMode ? [{ debugName: "vColor" }] : [])); compact = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "compact" }] : [])); // When in creation / add points mode, turn off crosshair interactivity // so that it doesn't accidentally steal clicks etc. interactionMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_6__.InteractionModeService).interactionMode; rotationQuality = new _viewport_interaction_interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_8__.WheelQualityInteraction((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.renderSettingsStore)); enabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const interactionMode = this.interactionMode(); return interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.InteractionModeType.SELECT; }, ...(ngDevMode ? [{ debugName: "enabled" }] : [])); windowDetails = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_window_details_window_details_service__WEBPACK_IMPORTED_MODULE_9__.WindowDetailsService); screenWidth = this.windowDetails.screenWidth; screenHeight = this.windowDetails.screenHeight; devicePixelRatio = this.windowDetails.devicePixelRatio; scaledSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.size() / this.devicePixelRatio(), ...(ngDevMode ? [{ debugName: "scaledSize" }] : [])); lineLength = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const width = this.screenWidth(); const height = this.screenHeight(); return Math.hypot(width, height); }, ...(ngDevMode ? [{ debugName: "lineLength" }] : [])); hitWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => HIT_TOLERANCE_PX / this.devicePixelRatio(), ...(ngDevMode ? [{ debugName: "hitWidth" }] : [])); hoverAxis = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "hoverAxis" }] : [])); hSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const baseSize = this.scaledSize(); const hoverAxis = this.hoverAxis(); return hoverAxis === 'h' ? baseSize + 2 : baseSize; }, ...(ngDevMode ? [{ debugName: "hSize" }] : [])); vSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const baseSize = this.scaledSize(); const hoverAxis = this.hoverAxis(); return hoverAxis === 'v' ? baseSize + 2 : baseSize; }, ...(ngDevMode ? [{ debugName: "vSize" }] : [])); middleGap = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { return 80 / this.devicePixelRatio(); }, ...(ngDevMode ? [{ debugName: "middleGap" }] : [])); shortArmLength = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => 18 / this.devicePixelRatio(), ...(ngDevMode ? [{ debugName: "shortArmLength" }] : [])); shortArmGap = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => 4 / this.devicePixelRatio(), ...(ngDevMode ? [{ debugName: "shortArmGap" }] : [])); shortArmStrokeWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.scaledSize() * 0.5, ...(ngDevMode ? [{ debugName: "shortArmStrokeWidth" }] : [])); // 2px against the default 3px crosshair width, matching the reticle in the reformation demo. centreDotRadius = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.scaledSize() * (2 / 3), ...(ngDevMode ? [{ debugName: "centreDotRadius" }] : [])); rectFill = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)('none', ...(ngDevMode ? [{ debugName: "rectFill" }] : [])); lastAngle; viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore); transform = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const [x, y] = this.position(); const rotation = this.rotation(); return `translate(${x} ${y}) rotate(${rotation})`; }, ...(ngDevMode ? [{ debugName: "transform" }] : [])); axisHover(axis) { this.hoverAxis.set(axis); } mouseDown(event) { // Only left-click rotates the crosshair. if (event.button !== 0) return; event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); this.lastAngle = this.mouseAngle(event); this.rectFill.set('transparent'); } mouseMove(event) { const startAngle = this.lastAngle; if (startAngle === undefined) { return; } event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); const newAngle = this.mouseAngle(event); const deltaAngle = startAngle - newAngle; this.lastAngle = newAngle; const viewportId = this.viewportId(); if (viewportId && !_viewport_ids__WEBPACK_IMPORTED_MODULE_7__.NON_DEGRADING_VIEWPORT_ID_LIST.includes(viewportId)) { this.rotationQuality.start(); } this.viewportStore.rotateCrosshair(this.axis(), deltaAngle); } mouseUp() { this.lastAngle = undefined; this.rectFill.set('none'); } mouseAngle(event) { const { offsetX, offsetY } = event; const [x, y] = this.position(); const dx = offsetX - x; const dy = offsetY - y; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.rad2deg)(Math.atan2(dy, dx)); } static ɵfac = function CrosshairComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CrosshairComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdefineComponent"]({ type: CrosshairComponent, selectors: [["", "lib-crosshair", ""]], inputs: { axis: [1, "axis"], viewportId: [1, "viewportId"], position: [1, "position"], rotation: [1, "rotation"], size: [1, "size"], hColor: [1, "hColor"], vColor: [1, "vColor"], compact: [1, "compact"] }, attrs: _c0, decls: 3, vars: 3, consts: [[3, "mousedown", "mousemove", "mouseup"], ["y1", "0", "y2", "0", "pointer-events", "none"], ["x1", "0", "x2", "0", "pointer-events", "none"], ["cx", "0", "cy", "0", "pointer-events", "none"], ["x1", "0", "x2", "0", 3, "mouseover", "mouseout"], ["y1", "0", "y2", "0", 3, "mouseover", "mouseout"]], template: function CrosshairComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementStart"](0, "g", 0); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomListener"]("mousedown", function CrosshairComponent_Template_g_mousedown_0_listener($event) { return ctx.mouseDown($event); })("mousemove", function CrosshairComponent_Template_g_mousemove_0_listener($event) { return ctx.mouseMove($event); })("mouseup", function CrosshairComponent_Template_g_mouseup_0_listener() { return ctx.mouseUp(); }); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditionalCreate"](1, CrosshairComponent_Conditional_1_Template, 5, 23)(2, CrosshairComponent_Conditional_2_Template, 11, 55); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵattribute"]("pointer-events", ctx.enabled() && !ctx.compact() ? "painted" : "none")("transform", ctx.transform()); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_10__["ɵɵconditional"](ctx.compact() ? 1 : 2); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 71848 /*!*******************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/viewport-overlay/viewport-overlay.component.ts ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportOverlay: () => (/* binding */ ViewportOverlay) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _crosshair_crosshair_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./crosshair/crosshair.component */ 86026); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["svgRoot"]; function ViewportOverlay_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](0, "g", 2); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("size", ctx_r0.crosshairSize())("axis", ctx_r0.viewportAxis())("viewportId", ctx_r0.viewportId())("position", ctx_r0.crosshairCenter())("rotation", ctx_r0.crosshairRotation())("hColor", ctx_r0.crosshairColors().h)("vColor", ctx_r0.crosshairColors().v)("compact", ctx_r0.compact()); } } class ViewportOverlay { viewportId = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "viewportId" }] : [])); viewportAxis = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "viewportAxis" }] : [])); cameraDetails = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "cameraDetails" }] : [])); crosshairRotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "crosshairRotation" }] : [])); crosshairColors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)({ h: 'var(--p-app-viewport-axis-axial)', v: 'var(--p-app-viewport-axis-sagittal)' }, ...(ngDevMode ? [{ debugName: "crosshairColors" }] : [])); compact = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "compact" }] : [])); svgRoot = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('svgRoot'); renderingEngine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_3__.RenderingEngineService); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.viewportStore); orchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_5__.VolumeViewerOrchestrator); crosshairSize = this.viewportStore.crosshairSize; constructor() { setTimeout(() => this.checkForViewport(), 10); } showCrosshairs = this.viewportStore.showCrosshairs; // TODO: Find better way to trigger the crosshair update after // the viewport is initialized checkForViewport() { const viewportId = this.viewportId(); const viewport = this.renderingEngine.getActiveViewports().find(viewport => viewport.id === viewportId); if (viewport) { this.viewportStore.updateIntersection([...this.viewportStore.intersection()]); } else { setTimeout(() => this.checkForViewport(), 10); } } crosshairCenter = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this.orchestrator.cacheBuster(); this.orchestrator.crosshairCacheBuster(); this.cameraDetails(); // Works like a cache buster currently const viewportId = this.viewportId(); const svg = this.svgRoot().nativeElement; const intersection = this.viewportStore.intersection(); const viewport = this.renderingEngine.getActiveViewports().find(viewport => viewport.id === viewportId); if (!viewport) { return [svg.clientWidth / 2, svg.clientHeight / 2]; } return viewport.worldToCanvas([...intersection]); }, ...(ngDevMode ? [{ debugName: "crosshairCenter" }] : [])); static ɵfac = function ViewportOverlay_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportOverlay)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineComponent"]({ type: ViewportOverlay, selectors: [["lib-viewport-overlay"]], viewQuery: function ViewportOverlay_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵviewQuerySignal"](ctx.svgRoot, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵqueryAdvance"](); } }, inputs: { viewportId: [1, "viewportId"], viewportAxis: [1, "viewportAxis"], cameraDetails: [1, "cameraDetails"], crosshairRotation: [1, "crosshairRotation"], crosshairColors: [1, "crosshairColors"], compact: [1, "compact"] }, decls: 3, vars: 1, consts: [["svgRoot", ""], [1, "absolute", "z-[1]", "h-full", "w-full", "overflow-hidden"], ["lib-crosshair", "", 3, "size", "axis", "viewportId", "position", "rotation", "hColor", "vColor", "compact"]], template: function ViewportOverlay_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "svg", 1, 0); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](2, ViewportOverlay_Conditional_2_Template, 1, 8, ":svg:g", 2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx.showCrosshairs() ? 2 : -1); } }, dependencies: [_crosshair_crosshair_component__WEBPACK_IMPORTED_MODULE_6__.CrosshairComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 60538 /*!********************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/volume-rendering-popover.service.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeRenderingPopoverService: () => (/* binding */ VolumeRenderingPopoverService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./viewport-ids */ 85309); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./volume-viewer-orchestrator.service */ 66035); class VolumeRenderingPopoverService { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_6__.getLogger)(VolumeRenderingPopoverService.name); viewerOrchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_8__.VolumeViewerOrchestrator); renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_4__.renderSettingsStore); engine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_2__.RenderingEngineService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); clippingRangeMin = 0; clippingRangeMax = 150; sliceGap = 1; seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)('', ...(ngDevMode ? [{ debugName: "seriesUid" }] : [])); getVolumeScalarRange = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.getVolumeScalarRange; onDragStart = () => this.viewerOrchestrator.decrease3dViewportImageQuality(); onDragEnd = () => this.viewerOrchestrator.increase3dViewportImageQuality(); get scalarRange() { return this.getVolumeScalarRange((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.getViewport)(this.engine.ENGINE_ID, _viewport_ids__WEBPACK_IMPORTED_MODULE_7__.VIEWPORT_IDS.REFORMAT)); } getVolumeRenderingFormConfig() { const seriesWindow = this.viewerOrchestrator.seriesWindowState(this.seriesUid()); if (!seriesWindow) { this.log.error(`Series window state not found for series UID: ${this.seriesUid()}`); return []; } const options = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(Object.values(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS).map(({ label, selectedPreset: value }) => ({ label, value })), ...(ngDevMode ? [{ debugName: "options" }] : [])); const defaultOption = this.renderSettingsStore.volumeSettings(); const currentOption = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(defaultOption ?? _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC], ...(ngDevMode ? [{ debugName: "currentOption" }] : [])); let presetSpecific = []; switch (currentOption().selectedPreset) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.ENDO: { presetSpecific = this.getEndovascularSliders(defaultOption); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC: case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.XRAY: { presetSpecific = this.getFluoroscopyXraySliders(defaultOption); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.MIP: { presetSpecific = this.getMipSliders(defaultOption); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.VASCULAR: { presetSpecific = this.getVascularSliders(defaultOption); break; } } return [...this.getPresetSelectConfig(options, defaultOption), ...presetSpecific, ...this.getClippingSliders(defaultOption)]; } getPresetSelectConfig(options, defaultOption) { return [{ defaultValue: defaultOption.selectedPreset, label: 'volumeRenderingSettings.preset', name: 'selectedPreset', onChange: form => { const selectedPresetValue = form.selectedPreset().value(); this.renderSettingsStore.selectVolumePreset(selectedPresetValue); const preset = this.renderSettingsStore.volumeSettings(); if (!preset) return; }, options, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SELECT }]; } getFluoroscopyXraySliders(defaultOption) { const presetDefault = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[defaultOption.selectedPreset]; return [{ defaultValue: defaultOption.threshold ?? 0, label: 'volumeRenderingSettings.threshold', max: this.scalarRange[1], min: this.scalarRange[0], name: 'threshold', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ threshold: form.threshold?.().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.threshold?.().value.set(presetDefault.threshold); this.renderSettingsStore.updateVolumeSettings({ threshold: presetDefault.threshold }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.brightness ?? 0, disabled: this.renderSettingsStore.volumeSettings()?.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.ENDO, hasDivider: true, label: 'volumeRenderingSettings.brightness', max: 1.5, min: -1, name: 'brightness', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ brightness: form.brightness?.().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.brightness?.().value.set(presetDefault.brightness); this.renderSettingsStore.updateVolumeSettings({ brightness: presetDefault.brightness }); }, step: 0.01, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }]; } /** MIP just projects the highest HU along each ray, so the result is a plain HU image - windowed * with width/level like any other CT image (MPR included), not the attenuation curve fluoro/ * xray use. Reuses their threshold/brightness field names under the hood (threshold = window * width, brightness = window level), but the sliders are labeled Window width/level since * that's what they actually are; bounds are MIP-specific, mirroring the MPR window drag * interaction's own (window-settings-interaction.ts) rather than fluoro/xray's ranges. */ getMipSliders(defaultOption) { const presetDefault = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.MIP]; const [scalarMin, scalarMax] = this.scalarRange; const windowWidthMax = Math.max(1, (scalarMax - scalarMin) * 2); return [{ defaultValue: defaultOption.threshold ?? 0, label: 'volumeRenderingSettings.windowWidth', max: windowWidthMax, min: 1, name: 'threshold', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ threshold: form.threshold?.().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.threshold?.().value.set(presetDefault.threshold); this.renderSettingsStore.updateVolumeSettings({ threshold: presetDefault.threshold }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.brightness ?? 0, hasDivider: true, label: 'volumeRenderingSettings.windowLevel', max: scalarMax, min: scalarMin, name: 'brightness', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ brightness: form.brightness?.().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.brightness?.().value.set(presetDefault.brightness); this.renderSettingsStore.updateVolumeSettings({ brightness: presetDefault.brightness }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }]; } getEndovascularSliders(defaultOption) { const presetDefault = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.ENDO]; return [{ defaultValue: defaultOption.airTissueThreshold ?? 0, label: 'volumeRenderingSettings.airTissueThreshold', max: form => form.tissueBloodThreshold?.().value() ?? 0, min: this.scalarRange[0], name: 'airTissueThreshold', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ airTissueThreshold: form.airTissueThreshold?.().value() ?? 0 }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.airTissueThreshold?.().value.set(presetDefault.airTissueThreshold); this.renderSettingsStore.updateVolumeSettings({ airTissueThreshold: presetDefault.airTissueThreshold }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.tissueBloodThreshold ?? 0, label: 'volumeRenderingSettings.tissueBloodThreshold', max: form => form.bloodCalciumThreshold?.().value() ?? 0, min: form => form.airTissueThreshold?.().value() ?? 0, name: 'tissueBloodThreshold', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ tissueBloodThreshold: form.tissueBloodThreshold?.().value() ?? 0 }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.tissueBloodThreshold?.().value.set(presetDefault.tissueBloodThreshold); this.renderSettingsStore.updateVolumeSettings({ tissueBloodThreshold: presetDefault.tissueBloodThreshold }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.bloodCalciumThreshold ?? 0, hasDivider: true, label: 'volumeRenderingSettings.bloodCalciumThreshold', max: this.scalarRange[1], min: form => form.tissueBloodThreshold?.().value() ?? 0, name: 'bloodCalciumThreshold', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ bloodCalciumThreshold: form.bloodCalciumThreshold?.().value() ?? 0 }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { form.bloodCalciumThreshold?.().value.set(presetDefault.bloodCalciumThreshold); this.renderSettingsStore.updateVolumeSettings({ bloodCalciumThreshold: presetDefault.bloodCalciumThreshold }); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }]; } getVascularSliders(defaultOption) { const presetDefault = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.VASCULAR]; // While previewing, the tissue-blood/blood-calcium sliders drive the segmentation's // minHU/maxHU bounds instead of the color-ramp thresholds — before preview and // after accept, they drive the color ramp as usual. const isPreviewing = this.viewerOrchestrator.vascularSegmentationState() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VascularSegmentationState.PREVIEWING; return [{ defaultValue: (isPreviewing ? defaultOption.minHU : defaultOption.tissueBloodThreshold) ?? 0, label: 'volumeRenderingSettings.tissueBloodThreshold', // Stays strictly below bloodCalciumThreshold — equal thresholds collapse the // CLUT remap (see remapClutToThresholds) to a single degenerate x-value. max: form => (form.bloodCalciumThreshold?.().value() ?? 0) - 1, min: this.scalarRange[0], name: 'tissueBloodThreshold', onChange: form => { const value = form.tissueBloodThreshold?.().value() ?? 0; if (isPreviewing) { this.renderSettingsStore.updateVolumeSettings({ minHU: value }); this.livePreviewFromSettings(); return; } this.renderSettingsStore.updateVolumeSettings({ tissueBloodThreshold: value, vascularThresholdsAutoTuned: true }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, onSlideEnd: () => this.rePreviewIfPreviewing(), resetEvent: form => { if (isPreviewing) { form.tissueBloodThreshold?.().value.set(presetDefault.minHU); this.renderSettingsStore.updateVolumeSettings({ minHU: presetDefault.minHU }); this.rePreviewIfPreviewing(); return; } // Prefer this session's histogram-computed default over the static preset, // so "reset" restores the scan-specific starting point once one exists. const resetValue = defaultOption.vascularSessionDefaultTissueBloodThreshold ?? presetDefault.tissueBloodThreshold; form.tissueBloodThreshold?.().value.set(resetValue); this.renderSettingsStore.updateVolumeSettings({ tissueBloodThreshold: resetValue, // A deliberate reset — must not look "untouched" and re-trigger the auto-tune. vascularThresholdsAutoTuned: true }); }, tooltip: this.translate.instant(isPreviewing ? 'volumeRenderingSettings.tissueBloodThresholdPreviewTooltip' : 'volumeRenderingSettings.tissueBloodThresholdTooltip'), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: (isPreviewing ? defaultOption.maxHU : defaultOption.bloodCalciumThreshold) ?? 0, hasDivider: false, label: 'volumeRenderingSettings.bloodCalciumThreshold', max: this.scalarRange[1], // Stays strictly above tissueBloodThreshold — see the matching comment there. min: form => (form.tissueBloodThreshold?.().value() ?? 0) + 1, name: 'bloodCalciumThreshold', onChange: form => { const value = form.bloodCalciumThreshold?.().value() ?? 0; if (isPreviewing) { this.renderSettingsStore.updateVolumeSettings({ maxHU: value }); this.livePreviewFromSettings(); return; } this.renderSettingsStore.updateVolumeSettings({ bloodCalciumThreshold: value, vascularThresholdsAutoTuned: true }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, onSlideEnd: () => this.rePreviewIfPreviewing(), resetEvent: form => { if (isPreviewing) { form.bloodCalciumThreshold?.().value.set(presetDefault.maxHU); this.renderSettingsStore.updateVolumeSettings({ maxHU: presetDefault.maxHU }); this.rePreviewIfPreviewing(); return; } // Prefer this session's histogram-computed default over the static preset, // so "reset" restores the scan-specific starting point once one exists. const resetValue = defaultOption.vascularSessionDefaultBloodCalciumThreshold ?? presetDefault.bloodCalciumThreshold; form.bloodCalciumThreshold?.().value.set(resetValue); this.renderSettingsStore.updateVolumeSettings({ bloodCalciumThreshold: resetValue, // A deliberate reset — must not look "untouched" and re-trigger the auto-tune. vascularThresholdsAutoTuned: true }); }, tooltip: this.translate.instant(isPreviewing ? 'volumeRenderingSettings.bloodCalciumThresholdPreviewTooltip' : 'volumeRenderingSettings.bloodCalciumThresholdTooltip'), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.outlierOpacity ?? 0, // Only takes effect once a mask is applied — the shader doesn't // consult it before then (pre-mask/previewing all voxels render // through the normal CT ramp). disabled: this.viewerOrchestrator.vascularSegmentationState() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VascularSegmentationState.APPLIED, hasDivider: true, label: 'volumeRenderingSettings.outlierOpacity', max: 1, min: 0, name: 'outlierOpacity', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ outlierOpacity: form.outlierOpacity?.().value() ?? 0 }); }, resetEvent: form => { form.outlierOpacity?.().value.set(presetDefault.outlierOpacity); this.renderSettingsStore.updateVolumeSettings({ outlierOpacity: presetDefault.outlierOpacity }); }, step: 0.01, tooltip: this.translate.instant('volumeRenderingSettings.outlierOpacityTooltip'), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, ...this.getVascularSegmentationButtons()]; } rePreviewIfPreviewing() { if (this.viewerOrchestrator.vascularSegmentationState() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VascularSegmentationState.PREVIEWING) { this.viewerOrchestrator.previewVascularMask(); } } /** The onChange handlers write the store first, so current settings carry * the dragged value. */ livePreviewFromSettings() { const settings = this.renderSettingsStore.volumeSettings(); if (!('minHU' in settings)) return; this.viewerOrchestrator.previewVascularMaskLive({ clusterSize: settings.clusterSize, erosionRadius: settings.erosionRadius, gridStep: settings.gridStep, maxHU: settings.maxHU, minHU: settings.minHU }); } getVascularSegmentationButtons() { const state = this.viewerOrchestrator.vascularSegmentationState(); if (state === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VascularSegmentationState.APPLIED) { return [{ defaultValue: 0, hasDivider: true, label: 'volumeRenderingSettings.revertSegmentation', name: 'revertSegmentation', onClick: () => this.viewerOrchestrator.revertVascularMask(), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.BUTTON }]; } if (state === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VascularSegmentationState.PREVIEWING) { const computing = this.viewerOrchestrator.vascularMaskComputing(); return [{ defaultValue: 0, disabled: computing, hasDivider: false, label: 'volumeRenderingSettings.acceptSegmentation', name: 'acceptSegmentation', onClick: () => this.viewerOrchestrator.acceptVascularMask(), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.BUTTON }, { defaultValue: 0, disabled: computing, hasDivider: true, label: 'volumeRenderingSettings.refuseSegmentation', name: 'refuseSegmentation', onClick: () => this.viewerOrchestrator.refuseVascularMask(), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.BUTTON }]; } return [{ defaultValue: 0, hasDivider: true, label: 'volumeRenderingSettings.previewSegmentation', name: 'previewSegmentation', onClick: () => this.viewerOrchestrator.previewVascularMask(), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.BUTTON }]; } getClippingSliders(defaultOption) { const presetDefault = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.VOLUME_RENDERING_PRESETS[defaultOption.selectedPreset]; return [{ defaultValue: Math.abs(defaultOption.distalDepth), label: 'volumeRenderingSettings.distalDepth', max: this.clippingRangeMax, // Store is the negated magnitude; floor at sliceGap so an unrepresentable 0 can't desync it from the display. min: this.sliceGap, name: 'distalDepth', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ distalDepth: -form.distalDepth().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { const { distalDepth } = presetDefault; this.renderSettingsStore.updateVolumeSettings({ distalDepth }); form.distalDepth().value.set(Math.abs(distalDepth)); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.proximalDepth, label: 'volumeRenderingSettings.proximalDepth', max: this.clippingRangeMax, min: this.clippingRangeMin, name: 'proximalDepth', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ proximalDepth: form.proximalDepth().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { const { proximalDepth } = presetDefault; this.renderSettingsStore.updateVolumeSettings({ proximalDepth }); form.proximalDepth().value.set(proximalDepth); }, step: 2, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }, { defaultValue: defaultOption.imageQuality, label: 'volumeRenderingSettings.imageQuality', max: 110, min: 0, name: 'imageQuality', onChange: form => { this.renderSettingsStore.updateVolumeSettings({ imageQuality: form.imageQuality().value() }); }, onDragEnd: this.onDragEnd, onDragStart: this.onDragStart, resetEvent: form => { const { imageQuality } = presetDefault; this.renderSettingsStore.updateVolumeSettings({ imageQuality }); form.imageQuality().value.set(imageQuality); }, step: 0.1, type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.SettingsPopoverField.SLIDER }]; } static ɵfac = function VolumeRenderingPopoverService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VolumeRenderingPopoverService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: VolumeRenderingPopoverService, factory: VolumeRenderingPopoverService.ɵfac }); } /***/ }, /***/ 66035 /*!**********************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/volume-viewer-orchestrator.service.ts ***! \**********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeViewerOrchestrator: () => (/* binding */ VolumeViewerOrchestrator) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @cornerstonejs/core */ 50600); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _kitware_vtk_js_Rendering_OpenGL_VolumeMapper__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/OpenGL/VolumeMapper */ 54143); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _work_session_work_session_service__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../work-session/work-session.service */ 82757); /* harmony import */ var _camera_animation_service__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./camera-animation.service */ 76045); /* harmony import */ var _cpr_cpr_config__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./cpr/cpr-config */ 17924); /* harmony import */ var _provide_volume_viewer__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./provide-volume-viewer */ 21321); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./viewport-ids */ 85309); /* harmony import */ var _viewport_interaction_interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./viewport-interaction/interactions/wheel-quality-interaction */ 78730); const VASCULAR_REAPPLY_ERROR = 'Failed to re-apply vascular mask'; // minHU/maxHU are the segmentation-inclusive bounds, not the ramp's own color-transition // points - they need to stay wider than tissueBloodThreshold/bloodCalciumThreshold or // voxels just outside the ramp but still legitimately tissue/blood/calcium get excluded // from segmentation entirely. Margins match the static preset's own relationship (170 vs // 215, 1000 vs 588) so a per-scan auto-tuned ramp gets the same proportional headroom. const VASCULAR_MIN_HU_MARGIN = 45; const VASCULAR_MAX_HU_MARGIN = 412; class VolumeViewerOrchestrator { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_16__.getLogger)(VolumeViewerOrchestrator.name); engine = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.RenderingEngineService); state = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_14__.volumeViewerStore); loader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.VolumeLoaderService); status = this.state.status; imageIdsError = this.state.imageIdsError; viewportStates = this.state.viewportStates; isCachingSource = this.loader.isCachingSource; renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_14__.renderSettingsStore); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_14__.viewportStore); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_14__.AnnotationFacade); cameraAnimation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_camera_animation_service__WEBPACK_IMPORTED_MODULE_18__.CameraAnimationService); workSessionService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_work_session_work_session_service__WEBPACK_IMPORTED_MODULE_17__.WorkSessionService); workSessionLoaded$ = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_3__.toObservable)(this.workSessionService.workSessionLoaded); volumeLoaderService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_11__.VolumeLoaderService); cleanupFunctions = []; rotationQuality = new _viewport_interaction_interactions_wheel_quality_interaction__WEBPACK_IMPORTED_MODULE_22__.WheelQualityInteraction(this.renderSettingsStore); effectsReady = false; _cacheBuster = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "_cacheBuster" }] : [])); get cacheBuster() { return this._cacheBuster; } _crosshairCacheBuster = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "_crosshairCacheBuster" }] : [])); get crosshairCacheBuster() { return this._crosshairCacheBuster; } _annotationScaleCacheBuster = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "_annotationScaleCacheBuster" }] : [])); get annotationScaleCacheBuster() { return this._annotationScaleCacheBuster; } forceRerender() { this._cacheBuster.update(version => version + 1); } cameraRendered = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "cameraRendered" }] : [])); // The canvas keeps its default black until volumeSettingsEffect first paints it, which waits on // the work session and the volume. Until then the preset says nothing about what is on screen. volumeBackgroundPainted = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "volumeBackgroundPainted" }] : [])); volumeBackgroundIsLight = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.volumeBackgroundPainted() && this.renderSettingsStore.volumeSettings().selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.FLUOROSCOPIC, ...(ngDevMode ? [{ debugName: "volumeBackgroundIsLight" }] : [])); resetCameraRendered() { this.cameraRendered.set(false); } renderStoredCameras() { const viewportCamera = this.viewportStore.viewportCameras(); const { distalDepth, proximalDepth } = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.renderSettingsStore.volumeSettings()); for (const [viewportId, camera] of Object.entries(viewportCamera)) { const viewport = this.engine.getViewport(viewportId); viewport?.setCamera({ ...camera }); if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"] && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.hasVolumeActor)(viewport)) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.adjustProximalAndDistalClippingPlanes)(viewport, proximalDepth, distalDepth, false); } } this.engine.renderAll(); this.cameraRendered.set(true); } constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_provide_volume_viewer__WEBPACK_IMPORTED_MODULE_20__.VOLUME_VIEWER_OPTIONS, { optional: true }); this.engine.init().catch(error => this.log.error('Engine init failed', error)); } initEffects() { if (this.effectsReady) return; this.registerContextLostEvents(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.assertInInjectionContext)(this.initEffects); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const preset = this.renderSettingsStore.volumeSettings.selectedPreset(); const maximized = this.reformatMaximized(); const previewing = this.vascularSegmentationState() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING; (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { if (preset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) { this.idleImageQuality.set(maximized || previewing ? 70 : 90); } else { this.idleImageQuality.set(100); } }); }); // Keep the persisted enum in sync with the live signal, so save/reload has an // accurate record of where the segmentation flow currently is. (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const state = this.vascularSegmentationState(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { const settings = this.renderSettingsStore.volumeSettings(); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; this.renderSettingsStore.updateVolumeSettings({ vascularSegmentationState: state }); }); }); const cameraEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this._cacheBuster(); const ready = this.workSessionService.workSessionLoaded(); this.viewportStore.viewportCameras(); if (!ready) { return; } this.renderStoredCameras(); // The crosshair overlay projects through a live `worldToCanvas` that no signal reports. this._crosshairCacheBuster.update(version => version + 1); }, ...(ngDevMode ? [{ debugName: "cameraEffect" }] : [])); // Only update the headlight when the camera actually rotates (not on every mouse move). // Calling updateLightsGeometryToFollowCamera inside cameraEffect fires on every // intersection change (crosshair move), which runs on every mouse move and causes // light.modified() to mark VTK state dirty every frame, causing annotation creation flicker. const lightEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this._cacheBuster(); const ready = this.workSessionService.workSessionLoaded(); this.viewportStore.viewportAngulations(); this.viewportStore.isPosterior(); const selectedPreset = this.renderSettingsStore.volumeSettings.selectedPreset(); if (!ready) return; const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"] && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.hasVolumeActor)(viewport)) { viewport.getRenderer().updateLightsGeometryToFollowCamera?.(); if (selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.ENDO) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.raiseViewportKeyLight)(viewport); } const overlayRenderer = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.getAnnotationOverlayRenderer)(viewport.id); if (overlayRenderer) { for (const light of overlayRenderer.getLights()) { light.setLightTypeToHeadLight(); } overlayRenderer.updateLightsGeometryToFollowCamera?.(); } // Headlights exist only on the REFORMAT renderer; cameraEffect renders the MPRs. this.engine.renderViewports([_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT]); } }, ...(ngDevMode ? [{ debugName: "lightEffect" }] : [])); const volumeSettingsEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this._cacheBuster(); const ready = this.workSessionService.workSessionLoaded(); const settings = this.renderSettingsStore.volumeSettings(); const { distalDepth, proximalDepth, selectedPreset: presetName } = settings; const { brightness, presetSpecificSettings, threshold } = this.resolvePresetRenderParams(settings); // Will only change when volumeSettings change anyway const darkMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.renderSettingsStore.volumeIsDarkMode()); if (!ready) { return; } const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; const bg = darkMode ? 0 : 1; this.handleVascularPresetSwitch(viewport, presetName); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.maybeAutoTuneVascularThresholds(viewport, settings)); // On first run after session load, re-apply if segmentation was previously accepted if (this._lastPreset === undefined && presetName === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR && this.shouldReapplyVascularMask(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE, settings)) { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { this.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.APPLIED); this.runVascularMask('apply').catch(error => this.log.error(VASCULAR_REAPPLY_ERROR, error)); }); } this.engine.updateVolume3dViewportWindow({ brightness, lighting: presetSpecificSettings, presetName, render: true, threshold, thresholds: presetSpecificSettings, volume3dViewport: viewport, widths: presetSpecificSettings }); if (presetName === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.XRAY || presetName === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.MIP) { viewport.getRenderer().setBackground(0, 0, 0); } else if (presetName === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.FLUOROSCOPIC) { viewport.getRenderer().setBackground(1, 1, 1); } else { viewport.getRenderer().setBackground(bg, bg, bg); } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.adjustProximalAndDistalClippingPlanes)(viewport, proximalDepth, distalDepth, false); viewport.render(); this.volumeBackgroundPainted.set(true); this._lastPreset = presetName; }, ...(ngDevMode ? [{ debugName: "volumeSettingsEffect" }] : [])); // Separated from volumeSettingsEffect so that setLowQuality(true/false) on mousedown // does not re-trigger the full preset re-application and cause the 3D surface to flash. const qualityEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const ready = this.workSessionService.workSessionLoaded(); const imageQuality = this.renderSettingsStore.volumeSettings.imageQuality(); this.renderSettingsStore.volumeSettings.selectedPreset(); const forceLowQuality = this.renderSettingsStore.forceLowQuality(); if (!ready) return; const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; const degrade = forceLowQuality && imageQuality < 100; if (degrade) { this.swapToLodVolume(viewport); } else { this.restoreFullResVolume(viewport); } this.scheduleQualityRender(viewport, degrade); }, ...(ngDevMode ? [{ debugName: "qualityEffect" }] : [])); const windowEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this._cacheBuster(); const ready = this.workSessionService.workSessionLoaded(); const windowSettings = this.renderSettingsStore.windowSettings(); if (!ready) { return; } this.engine.updateMPRWindow(windowSettings.width, windowSettings.level); }, ...(ngDevMode ? [{ debugName: "windowEffect" }] : [])); const zoomEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { this._cacheBuster(); const zoom = this.viewportStore.zoom(); const { distalDepth, proximalDepth } = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.renderSettingsStore.volumeSettings()); for (const viewport of this.engine.getActiveViewports()) { // The CPR carriers are orchestrator-unregistered and hold their own fixed-FOV // cameras; `setZoom` rescales off the fit-to-canvas camera and would drop them // to whole-volume zoom until their next explicit camera write. if ((0,_cpr_cpr_config__WEBPACK_IMPORTED_MODULE_19__.isCprCarrierViewportId)(viewport.id)) continue; viewport.setZoom(zoom); if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"] && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.hasVolumeActor)(viewport)) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.adjustProximalAndDistalClippingPlanes)(viewport, proximalDepth, distalDepth, false); } } this.engine.renderAll(); // Ensure the crosshair updates this._crosshairCacheBuster.update(version => version + 1); this._annotationScaleCacheBuster.update(version => version + 1); }, ...(ngDevMode ? [{ debugName: "zoomEffect" }] : [])); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => { cameraEffect.destroy(); lightEffect.destroy(); qualityEffect.destroy(); volumeSettingsEffect.destroy(); windowEffect.destroy(); zoomEffect.destroy(); this.cameraAnimation.cancel(); this.cleanup(); }); this.effectsReady = true; } /** Whether the loaded series appeared multiphase but could not be separated. */ wasSeriesUnseparable(seriesUid, studyUid, storeUid) { return this.state.wasSeriesUnseparable(studyUid, seriesUid, storeUid); } seriesPhases(seriesUid) { return this.state.seriesPhasesState(seriesUid); } phaseSelection(seriesUid) { return this.state.phaseSelectionState(seriesUid); } setPhaseSelection(seriesUid, availablePhaseIds, activePhaseId) { this.state.setPhaseSelection(seriesUid, { activePhaseId, availablePhaseIds }); } switchActiveVolume(fromPhaseId, toPhaseId) { this.workSessionService.switchActiveVolume(fromPhaseId, toPhaseId); this.reapplyVascularStateForPhaseSwitch().catch(error => this.log.error(VASCULAR_REAPPLY_ERROR, error)); } /** * workSessionService.switchActiveVolume (just above) already swaps the whole * renderSettingsStore snapshot for the new phase, so its persisted minHU/maxHU/ * tissueBloodThreshold/etc. round-trip correctly on their own. What doesn't follow that * swap: vascularSegmentationState is a single live signal here, not derived from the * store, so it still reflects the phase being switched away from; and the GPU mask * itself is attached to the volume/mapper the caller's setActiveVolume just replaced, * so there's nothing to visually show for the new phase yet even once the signal is * corrected. Re-sync the signal and reapply/restore the mask to match the new phase's * own persisted state - mirroring handleVascularPresetSwitch's "switching to vascular" * branch, but triggered by a phase change with the preset held constant, which * handleVascularPresetSwitch's _lastPreset comparison never sees. */ reapplyVascularStateForPhaseSwitch() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const settings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this.renderSettingsStore.volumeSettings()); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; // Re-sync the live signal to the new phase's persisted state regardless of whether a // REFORMAT viewport exists right now - reattachVascularMaskAfterViewportRebuild reads // this same signal later if/when the viewport (re)builds, and needs it to already // reflect the new phase rather than whichever one was active when this ran. Only the // GPU reapplication below actually needs a live viewport. const segState = settings.vascularSegmentationState; _this.vascularSegmentationState.set(segState); const viewport = _this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; _this._vascularRunGeneration++; _this.cancelTrailingExactRePreview(); _this._livePreviewPending = undefined; // Cancel rather than wait out a full-resolution exact run left over from the old phase - // it can take seconds, and the phase switch shouldn't stall on it. if (_this._maskRunning) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cancelVascularFullRun)(); // Bumping the generation above only marks any in-flight runVascularMask/drainLivePreview // tick as stale for the next time IT checks - it doesn't stop it mid-flight, and once it // does notice, it still runs its own now-stale cleanup (discardStaleVascularResult), which // unconditionally detaches whatever mask is currently attached. Drain every such call // fully - not just whichever one happens to be tracked most recently, and including any // pending-mode continuation one chains into on completion - before attaching the new // phase's mask below, or a stale cleanup can land afterward and rip out what we just // attached, even a mask restored instantly from the exact cache. while (_this._activeVascularOperations.size > 0) { yield Promise.all(_this._activeVascularOperations); } if (segState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING) { _this.runMaskUnlessCached(viewport, 'preview'); return; } if (_this.shouldReapplyVascularMask(segState, settings)) { _this.runMaskUnlessCached(viewport, 'apply'); } })(); } get requestedActiveVolume() { return this.state.requestedActiveVolume; } clearRequestedActiveVolume() { this.state.requestActiveVolume(undefined); } whenWorkSessionLoaded() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this2.workSessionService.workSessionLoaded()) return; yield (0,rxjs__WEBPACK_IMPORTED_MODULE_4__.firstValueFrom)(_this2.workSessionLoaded$.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_5__.filter)(Boolean))); })(); } loadSeries(seriesUid, studyUid, storeUid, selectedPhaseIds) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const imageIds = yield _this3.state.loadSeries(studyUid, seriesUid, storeUid, selectedPhaseIds); if (imageIds.length === 0) { _this3.state.setStatus('idle'); } return imageIds; } catch (error) { _this3.log.error('Failed to load series images', error); _this3.state.setStatus('error'); _this3.state.setImageIdsError(error); return []; } })(); } /** * Building the MPR/3D volumes from cached image binaries (loadVolumeImages) has no * error handling of its own upstream - an unhandled rejection here used to leave * status stuck at 'loading' forever (only a full page reload recovered), instead of * surfacing the same error state loadSeries already reports. */ reportVolumeLoadError(error) { this.log.error('Failed to load volume images', error); this.state.setStatus('error'); this.state.setImageIdsError(error); } resetForSeriesChange() { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this4.workSessionService.resetWorkSessionLoaded(); const viewports = _this4.state.registeredViewports(); for (const viewportId of Object.keys(viewports)) { _this4.engine.disable(viewportId); } _this4.volumeBackgroundPainted.set(false); _this4.state.resetForSeriesChange(); _this4.viewportStore.resetState(); _this4.resetVascularState(); yield _this4.engine.init(); })(); } resetVascularState() { this._vascularRunGeneration++; // A live worker would keep the previous study's volume resident indefinitely. (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.releaseVascularWorkers)(); this.cancelTrailingExactRePreview(); this._livePreviewPending = undefined; this.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE); this.vascularMaskComputing.set(false); this._maskRunning = false; this._pendingMaskMode = undefined; this._lastPreset = undefined; } setActiveVolume(volumeIds) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this5.engine.setActiveVolume(volumeIds); })(); } reapplyVolumeRenderSettings() { const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; const settings = this.renderSettingsStore.volumeSettings(); const { distalDepth, proximalDepth, selectedPreset: presetName } = settings; const { brightness, presetSpecificSettings, threshold } = this.resolvePresetRenderParams(settings); this.engine.updateVolume3dViewportWindow({ brightness, lighting: presetSpecificSettings, presetName, render: false, threshold, thresholds: presetSpecificSettings, volume3dViewport: viewport, widths: presetSpecificSettings }); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.adjustProximalAndDistalClippingPlanes)(viewport, proximalDepth, distalDepth, false); } // Bumped here since this is the one call site both the initial load and every // phase switch route through once their volume is ready (see loadSeries's // caller and onSelectVolume in volume-viewer.component.ts) - the pixel-range // computeds below key off it so they re-read the new volume's real range // instead of returning a stale value cached from before the load/switch. _volumeRangeRevision = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "_volumeRangeRevision" }] : [])); setVolumeCenter(volumeId) { this._volumeRangeRevision.update(revision => revision + 1); const volume = volumeId ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__["default"].getVolume(volumeId) : (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.getPrimaryImageVolume)(); if (volume) { const { dimensions, direction, origin, spacing } = volume; const halfInMM = gl_matrix__WEBPACK_IMPORTED_MODULE_9__.fromValues((dimensions[0] * spacing[0] - 1) / 2, (dimensions[1] * spacing[1] - 1) / 2, (dimensions[2] * spacing[2] - 1) / 2); const rotated = gl_matrix__WEBPACK_IMPORTED_MODULE_9__.transformMat3(gl_matrix__WEBPACK_IMPORTED_MODULE_9__.create(), halfInMM, direction); const center = gl_matrix__WEBPACK_IMPORTED_MODULE_9__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_9__.create(), origin, rotated); this.viewportStore.setVolumeDetails([center[0], center[1], center[2]]); } } registerContextLostEvents() { const offscreenCanvas = this.engine.getRenderWindow()?.getCanvas(); if (!offscreenCanvas) { this.log.warn('Offscreen canvas not found, skipping context lost event registration'); return; } const contextLostHandler = event => { event.preventDefault(); // enables the webglcontextrestored event to be delivered this.engine.destroy(); }; const contextRestoredHandler = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { globalThis.location.reload(); }); return function contextRestoredHandler() { return _ref.apply(this, arguments); }; }(); offscreenCanvas.addEventListener('webglcontextlost', contextLostHandler, false); offscreenCanvas.addEventListener('webglcontextrestored', contextRestoredHandler, false); this.cleanupFunctions.push(() => { offscreenCanvas.removeEventListener('webglcontextlost', contextLostHandler, false); offscreenCanvas.removeEventListener('webglcontextrestored', contextRestoredHandler, false); }); } registerViewport(element, options, seriesUid) { this.state.registerViewport(element, options, seriesUid); } deregisterViewport(viewportId) { this.state.deregisterViewport(viewportId); } increase3dViewportImageQuality() { // Let qualityEffect restore sample distance AND fluoro opacity together in one render. this.renderSettingsStore.setLowQuality(false); } decrease3dViewportImageQuality() { // Use this flag instead of directly setting the quality // so that we can easily restore the configured value this.renderSettingsStore.setLowQuality(true); } _qualityRenderScheduled = false; // Whether the OpenGL mapper's _animationRateSubscription has been registered yet. // It registers on the first renderPieceStart call; we do one synchronous VTK render // to guarantee it exists before invokeAnimationFrameRateUpdate sets _lastScale. _isdSubscriptionReady = false; swapToLodVolume(viewport) { const actor = viewport.getActors()[0]?.actor; if (!actor) return; const imageQuality = this.renderSettingsStore.volumeSettings.imageQuality(); const factor = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.computeImageSampleDistance)(imageQuality); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.applyImageSampleDistance)(actor, factor); } restoreFullResVolume(viewport) { const actor = viewport.getActors()[0]?.actor; if (!actor) return; (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.applyImageSampleDistance)(actor, 1); // eslint-disable-next-line @typescript-eslint/no-explicit-any (0,_kitware_vtk_js_Rendering_OpenGL_VolumeMapper__WEBPACK_IMPORTED_MODULE_8__.setForceFBOQuality)(actor.getMapper(), false); this._isdSubscriptionReady = false; } // Schedules a render via requestAnimationFrame so that rapid signal changes (e.g. slider // dragging) coalesce into a single GPU draw per vsync instead of one per signal tick. scheduleQualityRender(viewport, degrade) { if (this._qualityRenderScheduled) return; this._qualityRenderScheduled = true; requestAnimationFrame(() => { this._qualityRenderScheduled = false; if (degrade) { this.renderWithForcedAnimation(viewport); } else { viewport.render(); } }); } renderWithForcedAnimation(viewport) { const actor = viewport.getActors()[0]?.actor; // eslint-disable-next-line @typescript-eslint/no-explicit-any const mapper = actor?.getMapper?.(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const renderer = viewport.getRenderer(); const vtkWindow = renderer?.getVTKWindow?.(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const rwi = vtkWindow?.getInteractor?.(); if (!rwi || !mapper) { viewport.render(); return; } // For the first degraded render the OpenGL mapper's _animationRateSubscription hasn't been // registered yet (it registers inside renderPieceStart on first call). Drive one synchronous // VTK render here — bypassing Cornerstone's async pipeline — solely to register it. // NOTE: we intentionally do NOT call requestAnimation before this. requestAnimation sets // isAnimating=true which causes publicAPI.render() to skip forceRender() entirely, blocking // all Cornerstone-triggered renders. Keep isAnimating=false throughout. if (!this._isdSubscriptionReady) { renderer.setDraw(true); vtkWindow.render(); renderer.setDraw(false); this._isdSubscriptionReady = true; } // Set _lastScale = ISD² on the OpenGL mapper so the next renderPieceStart sees // _lastScale > 1.5 and activates _useSmallViewport → FBO downscaling. rwi.invokeAnimationFrameRateUpdate({}); // Signal renderPieceStart to activate FBO for ALL renders until restoreFullResVolume clears it. // We can't set properties on the logic mapper directly — VTK freezes publicAPI objects. // The flag stays set so every Cornerstone render fired during a drag also uses FBO. (0,_kitware_vtk_js_Rendering_OpenGL_VolumeMapper__WEBPACK_IMPORTED_MODULE_8__.setForceFBOQuality)(mapper, true); // Schedule through Cornerstone's normal pipeline so the blit to the visible canvas happens. viewport.render(); } /** * Animate the camera to an annotation. */ goToAnnotation(id) { const annotation = this.annotationFacade.getAnnotationById(id); if (!annotation || !(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.isRenderable)(annotation)) return; const normal = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.getNormal)(annotation); this.cameraAnimation.animateToPosition((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.getCentroid)(annotation), normal, { onSettle: () => this.increase3dViewportImageQuality(), onStart: () => this.decrease3dViewportImageQuality() }); } moveCrosshairToAnnotation(id) { const annotation = this.annotationFacade.getAnnotationById(id); if (!annotation || !(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.isRenderable)(annotation)) return; this.viewportStore.updateIntersection((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_13__.getCentroid)(annotation)); } seriesWindowState(seriesUid) { return this.state.seriesWindowState(seriesUid); } streamSeriesCacheProgress(seriesUid, storeUid) { return this.volumeLoaderService.streamSeriesCacheProgress(seriesUid, storeUid); } viewportsToEnable = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.state.viewportStates().filter(viewport => !!viewport.element && !viewport.isInitialized), { ...(ngDevMode ? { debugName: "viewportsToEnable" } : {}), equal: rxdb__WEBPACK_IMPORTED_MODULE_10__.deepEqual }); enableViewports(viewportConfig, volumeIds) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const promises = viewportConfig.map(/*#__PURE__*/function () { var _ref2 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({ element, id, type }) { if (!element) throw new Error(`No element for viewport ${id}`); const volumeId = type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.ViewportType.VOLUME_3D ? volumeIds.volume3dId : volumeIds.mprVolumeId; yield _this6.engine.enable(element, { id, type, volumeId }); return id; }); return function (_x) { return _ref2.apply(this, arguments); }; }()); return Promise.all(promises); })(); } completeViewports(enabledIds) { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this7.state.markViewportsInitialized(enabledIds); _this7.state.setStatus('ready'); _this7.engine.setViewportsReady(); if (enabledIds.includes(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT)) { _this7.reattachVascularMaskAfterViewportRebuild(); } })(); } // Re-enabling a viewport rebuilds its actor, dropping any attached GPU mask. reattachVascularMaskAfterViewportRebuild() { const segState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.vascularSegmentationState()); if (segState === 'none') return; const settings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.renderSettingsStore.volumeSettings()); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.isVascularGpuMaskAttached)(viewport)) return; this.runMaskUnlessCached(viewport, segState === 'previewing' ? 'preview' : 'apply'); } showVolumeRenderPanel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "showVolumeRenderPanel" }] : [])); toggleVolumeRenderPanel() { this.showVolumeRenderPanel.update(v => !v); } closeVolumeRenderPanel() { this.showVolumeRenderPanel.set(false); } showCtSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "showCtSettings" }] : [])); setCtSettingsVisible(open) { this.showCtSettings.set(open); } idleImageQuality = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(90, ...(ngDevMode ? [{ debugName: "idleImageQuality" }] : [])); reformatMaximized = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "reformatMaximized" }] : [])); setReformatMaximized(maximized) { this.reformatMaximized.set(maximized); } getVolumeScalarRangeForViewport(viewport) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.getVolumeScalarRange)(viewport); } volumeMaxPixelValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this._volumeRangeRevision(); const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return 3071; const [, max] = this.getVolumeScalarRangeForViewport(viewport); return max; }, ...(ngDevMode ? [{ debugName: "volumeMaxPixelValue" }] : [])); volumeMinPixelValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { this._volumeRangeRevision(); const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return -1024; const [min] = this.getVolumeScalarRangeForViewport(viewport); return min; }, ...(ngDevMode ? [{ debugName: "volumeMinPixelValue" }] : [])); showRenderQualityDevPanel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "showRenderQualityDevPanel" }] : [])); toggleRenderQualityDevPanel() { this.showRenderQualityDevPanel.update(v => !v); } closeRenderQualityDevPanel() { this.showRenderQualityDevPanel.set(false); } showEndoDevPanel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "showEndoDevPanel" }] : [])); toggleEndoDevPanel() { const opening = !this.showEndoDevPanel(); this.showEndoDevPanel.set(opening); if (opening) { this.renderSettingsStore.selectVolumePreset(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.ENDO); } } closeEndoDevPanel() { this.showEndoDevPanel.set(false); } editOrientationTargetId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "editOrientationTargetId" }] : [])); isEditingOrientation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.editOrientationTargetId() !== undefined, ...(ngDevMode ? [{ debugName: "isEditingOrientation" }] : [])); openEditOrientation(annotationId) { this.editOrientationTargetId.set(annotationId); } closeEditOrientation() { this.editOrientationTargetId.set(undefined); } isSettingsPanelOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.isEditingOrientation() || this.showVolumeRenderPanel() || this.showCtSettings(), ...(ngDevMode ? [{ debugName: "isSettingsPanelOpen" }] : [])); vascularMaskComputing = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "vascularMaskComputing" }] : [])); vascularSegmentationState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE, ...(ngDevMode ? [{ debugName: "vascularSegmentationState" }] : [])); vascularSegmentationApplied = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.vascularSegmentationState() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE, ...(ngDevMode ? [{ debugName: "vascularSegmentationApplied" }] : [])); _maskRunning = false; _pendingMaskMode; _lastPreset; showVascularDevPanel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "showVascularDevPanel" }] : [])); toggleVascularDevPanel() { const opening = !this.showVascularDevPanel(); this.showVascularDevPanel.set(opening); if (opening) { this.renderSettingsStore.selectVolumePreset(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR); } } closeVascularDevPanel() { this.showVascularDevPanel.set(false); } handleVascularPresetSwitch(viewport, presetName) { const segState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.vascularSegmentationState()); const settings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.renderSettingsStore.volumeSettings()); const switchingAway = presetName !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR && this._lastPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR; const switchingTo = presetName === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR && this._lastPreset !== undefined && this._lastPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR; if (switchingAway) { this._vascularRunGeneration++; if (segState !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.restoreVascularForPresetSwitch)(viewport); } if (!switchingTo) return; if (segState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING) { this.runMaskUnlessCached(viewport, 'preview'); return; } if (this.shouldReapplyVascularMask(segState, settings)) { this.runMaskUnlessCached(viewport, 'apply'); } } runMaskUnlessCached(viewport, mode) { const reapplied = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.instantlyReapplyVascularMask)(viewport, mode === 'preview' ? 'preview' : 'applied'); // A cached low-res live-preview result may reapply instantly (no flash), // but it must still be refreshed by an exact run. if (!reapplied || !(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.isVascularGpuMaskExact)(viewport)) { this.runVascularMask(mode).catch(error => this.log.error(VASCULAR_REAPPLY_ERROR, error)); } } shouldReapplyVascularMask(segState, settings) { return segState === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.APPLIED || 'hasAcceptedSegmentation' in settings && settings.hasAcceptedSegmentation; } /** Bumped on refuse, revert, preset switch away, and series reset; a worker * result whose captured generation no longer matches must not re-attach. */ _vascularRunGeneration = 0; /** The mask function already attached the stale result — detach it, dropping * the label cache when the segmentation was explicitly discarded. */ discardStaleVascularResult(viewport) { if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.vascularSegmentationState()) === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE) { this.restoreVascularMask(viewport); } else { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.restoreVascularForPresetSwitch)(viewport); } } /** Re-applies the vascular window settings and advances the segmentation * state — unless the run went stale, in which case the attach is undone. */ finishVascularRun(viewport, mode, generation) { if (generation !== this._vascularRunGeneration) { this.discardStaleVascularResult(viewport); return; } const currentSettings = this.renderSettingsStore.volumeSettings(); const { brightness, presetSpecificSettings, threshold } = this.resolvePresetRenderParams(currentSettings); this.engine.updateVolume3dViewportWindow({ brightness, lighting: presetSpecificSettings, presetName: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR, render: true, threshold, thresholds: presetSpecificSettings, volume3dViewport: viewport, widths: presetSpecificSettings }); this.vascularSegmentationState.set(mode === 'preview' ? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING : _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.APPLIED); } /** Entering preview fresh: snapshot the current color-ramp thresholds so revert can * restore this exact "initial" state later (accept overwrites the live ramp). * minHU/maxHU are seeded from the ramp the first time ever, and again any time the * ramp has moved since the last preview entry (e.g. the user reset/adjusted * tissueBloodThreshold/bloodCalciumThreshold in general mode) - detected by comparing * against that last-entry snapshot. Otherwise the popover's mode-aware sliders own * minHU/maxHU directly, so re-previewing after a revert/refuse with an untouched ramp * resumes from whatever was last tuned while previewing instead of reseeding over it. */ seedVascularPreviewEntry(mode, settings) { if (mode !== 'preview') return settings; if (!('minHU' in settings)) return settings; if (this.vascularSegmentationState() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE) return settings; const rampChangedSinceLastEntry = settings.tissueBloodThreshold !== settings.vascularPreviewEntryTissueBloodThreshold || settings.bloodCalciumThreshold !== settings.vascularPreviewEntryBloodCalciumThreshold; const patch = { vascularPreviewEntryBloodCalciumThreshold: settings.bloodCalciumThreshold, vascularPreviewEntryTissueBloodThreshold: settings.tissueBloodThreshold }; if (!settings.vascularPreviewBoundsSeeded || rampChangedSinceLastEntry) { patch.maxHU = settings.bloodCalciumThreshold + VASCULAR_MAX_HU_MARGIN; patch.minHU = settings.tissueBloodThreshold - VASCULAR_MIN_HU_MARGIN; patch.vascularPreviewBoundsSeeded = true; } this.renderSettingsStore.updateVolumeSettings(patch); return this.renderSettingsStore.volumeSettings(); } /** Every runVascularMask/drainLivePreview call currently in flight - see * reapplyVascularStateForPhaseSwitch, which must wait for ALL of them (not just * whichever call happened to run most recently - see trackVascularOperation) to fully * settle, including each one's own now-stale cleanup, before touching the mask itself. */ _activeVascularOperations = new Set(); /** Registers `run` in _activeVascularOperations for its lifetime. A single shared "latest * call" field would get overwritten by a second call that starts (and, via the * `_maskRunning` guard, often finishes near-instantly by just queuing a pending mode) * while an earlier, genuinely long-running call is still in flight - losing track of the * one that actually matters. Tracking every active call in a set instead means none of * them can be dropped just because another one started later. Entries never reject: a * waiter only needs to know each one is *done*, not how it ended. */ trackVascularOperation(run) { const settled = run.catch(() => { // Swallowed on purpose - see this method's doc comment above. }); this._activeVascularOperations.add(settled); settled.then(() => this._activeVascularOperations.delete(settled)); return run; } runVascularMask(mode) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this8.trackVascularOperation(_this8.runVascularMaskWork(mode)); })(); } runVascularMaskWork(mode) { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this9._maskRunning) { _this9._pendingMaskMode = mode; return; } let settings = _this9.renderSettingsStore.volumeSettings(); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; if (!('minHU' in settings)) return; const viewport = _this9.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; settings = _this9.seedVascularPreviewEntry(mode, settings); if (!('minHU' in settings)) return; _this9._maskRunning = true; _this9.vascularMaskComputing.set(true); // Drop any queued live tick and the trailing re-run so they don't // overwrite the exact result with a low-res one. _this9._livePreviewPending = undefined; _this9.cancelTrailingExactRePreview(); const generation = _this9._vascularRunGeneration; try { if (mode === 'preview') { yield _this9.paintApproximateFirstPreview(viewport, { clusterSize: settings.clusterSize, erosionRadius: settings.erosionRadius, gridStep: settings.gridStep, maxHU: settings.maxHU, minHU: settings.minHU }); } const maskFunction = mode === 'preview' ? _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.previewVascularRegionMask : _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.applyVascularRegionMask; const success = yield maskFunction(viewport, settings.minHU, settings.maxHU, undefined, settings.gridStep, settings.clusterSize, settings.erosionRadius); if (success) { _this9.finishVascularRun(viewport, mode, generation); } } finally { _this9._maskRunning = false; const pending = _this9._pendingMaskMode; _this9._pendingMaskMode = undefined; if (pending) { _this9.runVascularMask(pending).catch(error => _this9.log.error(VASCULAR_REAPPLY_ERROR, error)); } else { _this9.vascularMaskComputing.set(false); } } })(); } previewVascularMask() { return this.runVascularMask('preview'); } /** Paints the approximate low-res result before the exact run, so the first * preview isn't seconds of unchanged render. Awaited: 'previewing' must be * entered before the exact run starts so drags go live while it computes. */ paintApproximateFirstPreview(viewport, parameters) { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.isVascularGpuMaskAttached)(viewport)) return; const livePainted = yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.previewVascularRegionMaskLive)(viewport, parameters).catch(() => false); if (livePainted) _this0.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING); })(); } _livePreviewPending; _livePreviewRunning = false; _trailingExactRePreview; /** Live re-segmentation while a slider drags. Ticks coalesce — at most one * preview request in flight, on a worker isolated from exact runs. */ previewVascularMaskLive(parameters) { if (this.vascularSegmentationState() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING) return; const settings = this.renderSettingsStore.volumeSettings(); if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; // Dragging supersedes an in-flight exact run — cancel it (the rejected // promise clears the spinner); slide-end or the trailing re-run computes exact. if (this._maskRunning) (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.cancelVascularFullRun)(); this._livePreviewPending = parameters; this.drainLivePreview().catch(error => this.log.error(VASCULAR_REAPPLY_ERROR, error)); } drainLivePreview() { var _this1 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _this1.trackVascularOperation(_this1.drainLivePreviewWork()); })(); } drainLivePreviewWork() { var _this10 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this10._livePreviewRunning) return; _this10._livePreviewRunning = true; try { while (_this10._livePreviewPending) { const parameters = _this10._livePreviewPending; _this10._livePreviewPending = undefined; const viewport = _this10.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) break; const generation = _this10._vascularRunGeneration; yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.previewVascularRegionMaskLive)(viewport, parameters).catch(() => false); // Refused/reverted/preset-switched while this tick computed — undo the attach. if (generation !== _this10._vascularRunGeneration) { _this10.discardStaleVascularResult(viewport); return; } } } finally { _this10._livePreviewRunning = false; } _this10.scheduleTrailingExactRePreview(); })(); } /** Keyboard slider input never fires onSlideEnd, so every drained tick arms * a trailing exact re-run; a slide-end or newer tick supersedes it. */ scheduleTrailingExactRePreview() { this.cancelTrailingExactRePreview(); this._trailingExactRePreview = setTimeout(() => { this._trailingExactRePreview = undefined; if (this._maskRunning || this._livePreviewRunning || this._livePreviewPending) return; if (this.vascularSegmentationState() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.PREVIEWING) return; this.previewVascularMask().catch(error => this.log.error(VASCULAR_REAPPLY_ERROR, error)); }, 700); } cancelTrailingExactRePreview() { if (this._trailingExactRePreview === undefined) return; clearTimeout(this._trailingExactRePreview); this._trailingExactRePreview = undefined; } /** Resolves after the browser's paint for the next two frames, so a signal * flip made just before this actually reaches the screen before further * (blocking) work runs. */ waitForNextFrame() { const nextFrame = () => new Promise(resolve => requestAnimationFrame(() => resolve())); return nextFrame().then(nextFrame); } acceptVascularMask() { var _this11 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const viewport = _this11.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; if (!_this11.commitVascularPreview(viewport)) return; // Refining thresholds walks every voxel on the main thread — reuse the // same spinner the preview computation shows, and wait for it to // actually paint before that blocking work starts. _this11.vascularMaskComputing.set(true); yield _this11.waitForNextFrame(); try { _this11.refineVascularThresholdsIfPossible(viewport); const settings = _this11.renderSettingsStore.volumeSettings(); const { brightness, presetSpecificSettings, threshold } = _this11.resolvePresetRenderParams(settings); _this11.engine.updateVolume3dViewportWindow({ brightness, lighting: presetSpecificSettings, presetName: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR, render: true, threshold, thresholds: presetSpecificSettings, volume3dViewport: viewport, widths: presetSpecificSettings }); _this11.renderSettingsStore.updateVolumeSettings({ hasAcceptedSegmentation: true }); _this11.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.APPLIED); } catch (error) { _this11.log.error(VASCULAR_REAPPLY_ERROR, error); } finally { _this11.vascularMaskComputing.set(false); } })(); } refuseVascularMask() { const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; this._vascularRunGeneration++; this.restoreVascularMask(viewport); viewport.render(); this.renderSettingsStore.updateVolumeSettings({ hasAcceptedSegmentation: false }); this.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE); } revertVascularMask() { const viewport = this.engine.getViewport(_viewport_ids__WEBPACK_IMPORTED_MODULE_21__.VIEWPORT_IDS.REFORMAT); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"])) return; this._vascularRunGeneration++; this.restoreVascularMask(viewport); const settings = this.renderSettingsStore.volumeSettings(); if (settings.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) { const defaults = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR]; this.renderSettingsStore.updateVolumeSettings({ // Restore the exact ramp from right before preview last started; fall back to // this session's histogram-computed default, then the static preset, for the // (unexpected) case preview was never actually entered. bloodCalciumThreshold: settings.vascularPreviewEntryBloodCalciumThreshold ?? settings.vascularSessionDefaultBloodCalciumThreshold ?? defaults.bloodCalciumThreshold, hasAcceptedSegmentation: false, tissueBloodThreshold: settings.vascularPreviewEntryTissueBloodThreshold ?? settings.vascularSessionDefaultTissueBloodThreshold ?? defaults.tissueBloodThreshold, // A deliberate reset — must not look "untouched" and re-trigger the auto-tune. vascularThresholdsAutoTuned: true }); } else { viewport.render(); } this.vascularSegmentationState.set(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VascularSegmentationState.NONE); } // Seams over the @tomoverse/utils helpers so tests can spy on them; Vitest's barrel mock doesn't reliably intercept the bare imports on CI. commitVascularPreview(viewport) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.acceptVascularPreview)(viewport); } restoreVascularMask(viewport) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.restoreVascularRegionMask)(viewport); } computeAutoVascularThresholds(volume) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.computeAutoVascularThresholdsForVolume)(volume); } refineVascularThresholdsFromMask(volume) { return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.computeVascularThresholdsFromMask)(volume); } /** Seeds a per-scan starting ramp from the volume's own HU histogram the first * time Vascular mode is selected — gated on `vascularThresholdsAutoTuned` rather * than comparing against the static default, so a deliberate reset-to-default * (which also lands on those exact numbers) is never mistaken for "untouched" * and re-triggers the heuristic. */ maybeAutoTuneVascularThresholds(viewport, settings) { if (settings.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_12__.VolumeRenderingOption.VASCULAR) return; if (settings.vascularThresholdsAutoTuned) return; const volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__["default"].getVolume(viewport.getVolumeId()); if (!volume) return; const computed = this.computeAutoVascularThresholds(volume); if (!computed) { this.renderSettingsStore.updateVolumeSettings({ vascularThresholdsAutoTuned: true }); return; } this.renderSettingsStore.updateVolumeSettings({ ...computed, // Becomes this session's reset target, so "reset" restores the scan-specific // starting point instead of the generic static preset from then on. vascularSessionDefaultBloodCalciumThreshold: computed.bloodCalciumThreshold, vascularSessionDefaultTissueBloodThreshold: computed.tissueBloodThreshold, vascularThresholdsAutoTuned: true }); } /** Tightens the ramp to the accepted mask's own vessel-voxel HU range — * the authoritative signal at accept time, so it always overrides whatever * was there before (default, auto-tuned, or user-adjusted). */ refineVascularThresholdsIfPossible(viewport) { const volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__["default"].getVolume(viewport.getVolumeId()); if (!volume) return; const refined = this.refineVascularThresholdsFromMask(volume); if (!refined) return; this.renderSettingsStore.updateVolumeSettings({ ...refined, vascularThresholdsAutoTuned: true }); } isPosterior = this.viewportStore.isPosterior; updateIsPosterior(isPosterior) { this.viewportStore.updatePosterior(isPosterior); } ccAngle = this.viewportStore.primaryViewportAngulations.cc; rlAngle = this.viewportStore.primaryViewportAngulations.rl; cameraRlChanged(newValueRL) { this.rotationQuality.start(); this.viewportStore.updateAngulations({ rl: newValueRL }); } cameraCcChanged(newValueCC) { this.rotationQuality.start(); this.viewportStore.updateAngulations({ cc: newValueCC }); } resetAngulations() { this.viewportStore.resetAngulations(); this.viewportStore.resetCrosshairPosition(); } copyAngulations(viewportAxisState) { const angulationsForViewport = this.viewportStore.viewportAngulations()[viewportAxisState]; if (!angulationsForViewport) { this.log.warn(`Viewport with id ${viewportAxisState} not found or has no angulations`); return; } const angulationsString = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_15__.formatAngulationtxt)(angulationsForViewport, this.viewportStore.isPosterior()); navigator.clipboard.writeText(angulationsString).catch(error => this.log.error(`Could not copy angulations: ${error}`)); } resolvePresetRenderParams(settings) { return { brightness: 'brightness' in settings ? settings.brightness : 0, presetSpecificSettings: 'tissueBloodThreshold' in settings ? settings : undefined, threshold: 'threshold' in settings ? settings.threshold : 0 }; } cleanup() { for (const cleanupFunction of this.cleanupFunctions) cleanupFunction(); this.cleanupFunctions.length = 0; } } /***/ }, /***/ 28828 /*!***********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/volume-viewer.component.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeViewerComponent: () => (/* binding */ VolumeViewerComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_accordion__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/accordion */ 45913); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../annotation-card/annotation-card.component */ 86628); /* harmony import */ var _annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../annotation-menu/annotation-menu-item.service */ 39860); /* harmony import */ var _annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../annotation-menu/components/annotation-menu-item.component */ 45731); /* harmony import */ var _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../annotation-menu/components/annotation-menu.component */ 13609); /* harmony import */ var _annotation_menu_menu_tracker_service__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../annotation-menu/menu-tracker.service */ 61487); /* harmony import */ var _chamber_chamber_service__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../chamber/chamber.service */ 16592); /* harmony import */ var _interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../interaction-mode/interaction-mode.service */ 72754); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _protocols__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../protocols */ 61632); /* harmony import */ var _s_curve_graph_s_curve_graph_component__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../s-curve-graph/s-curve-graph.component */ 1336); /* harmony import */ var _window_window_service__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../window/window.service */ 26914); /* harmony import */ var _annotation_actors_annotation_actors_service__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./annotation-actors/annotation-actors.service */ 12100); /* harmony import */ var _cpr_cpr_config__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./cpr/cpr-config */ 17924); /* harmony import */ var _cpr_cpr_workspace_component__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./cpr/cpr-workspace.component */ 11095); /* harmony import */ var _cpr_cpr_service__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./cpr/cpr.service */ 26144); /* harmony import */ var _ct_popover_service__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./ct-popover.service */ 20974); /* harmony import */ var _endo_dev_panel_endo_dev_panel_component__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./endo-dev-panel/endo-dev-panel.component */ 50108); /* harmony import */ var _orientation_form_config__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./orientation-form-config */ 1894); /* harmony import */ var _render_quality_dev_panel_render_quality_dev_panel_component__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./render-quality-dev-panel/render-quality-dev-panel.component */ 33032); /* harmony import */ var _vascular_dev_panel_vascular_dev_panel_component__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./vascular-dev-panel/vascular-dev-panel.component */ 74278); /* harmony import */ var _viewport_ids__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./viewport-ids */ 85309); /* harmony import */ var _viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./viewport-interaction/viewport-interaction.service */ 46184); /* harmony import */ var _viewport_overlay_viewport_overlay_component__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./viewport-overlay/viewport-overlay.component */ 71848); /* harmony import */ var _volume_rendering_popover_service__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./volume-rendering-popover.service */ 60538); /* harmony import */ var _volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./volume-viewer-orchestrator.service */ 66035); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["ctxMenu"]; const _c1 = ["alignMenu"]; const _c2 = () => ({ style: "display: none" }); const _c3 = a0 => ({ root: a0 }); const _c4 = a0 => ({ $implicit: a0, includeViewportSwap: true }); const _c5 = a0 => ({ $implicit: a0, includeViewportSwap: false }); const _c6 = () => ({ root: "w-xs max-w-full" }); const _c7 = () => ({ root: "py-2" }); const _c8 = () => ({ content: "py-2 border-surface-800 border-t" }); const _c9 = (a0, a1) => ({ header: a0, content: a1, wrapper: "rounded-lg border-none" }); function VolumeViewerComponent_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "pre"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "json"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 1, ctx_r0.viewerOrchestrator.imageIdsError())); } } function VolumeViewerComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 17); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtext"](1, " Error loading volume data. "); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](2, VolumeViewerComponent_Conditional_0_Conditional_2_Template, 3, 3, "pre"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.imageIdsError() ? 2 : -1); } } function VolumeViewerComponent_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 22)(1, "p-select", 27); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("ngModelChange", function VolumeViewerComponent_Conditional_1_Conditional_3_Template_p_select_ngModelChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r3); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onSelectVolume($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("options", ctx_r0.phaseSelectOptions())("ngModel", ctx_r0.selectedPhaseId())("disabled", ctx_r0.isVolumeSwitching())("ariaLabel", ctx_r0.volumeWord()); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_1_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementContainer"](0); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](0, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_1_ng_container_0_Template, 1, 0, "ng-container", 29); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); const viewportBase_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](13); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("ngTemplateOutlet", viewportBase_r5)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction1"](2, _c4, ctx_r0.viewportIds.AXIAL)); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_3_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementContainer"](0); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](0, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_3_ng_container_0_Template, 1, 0, "ng-container", 29); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); const viewportBase_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](13); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("ngTemplateOutlet", viewportBase_r5)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction1"](2, _c4, ctx_r0.viewportIds.SAGITTAL)); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_5_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementContainer"](0); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](0, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_5_ng_container_0_Template, 1, 0, "ng-container", 29); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); const viewportBase_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](13); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("ngTemplateOutlet", viewportBase_r5)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction1"](2, _c5, ctx_r0.viewportIds.CORONAL)); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_7_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementContainer"](0); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](0, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_7_ng_container_0_Template, 1, 0, "ng-container", 29); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); const viewportBase_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](13); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("ngTemplateOutlet", viewportBase_r5)("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction1"](2, _c5, ctx_r0.viewportIds.REFORMAT)); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_9_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 30)(1, "div", 31)(2, "lib-viewport-button", 32); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("click", function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_9_Template_lib_viewport_button_click_2_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onToggleMaximizeViewport(ctx_r0.PanelName.S_CURVE_GRAPH)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](5, "lib-viewport-button", 33); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](6, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](7, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("click", function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_9_Template_lib_viewport_button_click_5_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r6); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.moveSCurveGraphToSidebar()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](8, "div", 34)(9, "div", 35); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](10, "lib-s-curve-graph", 36); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); const maximized_r7 = ctx_r0.sCurveMaximized(); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](3, 7, maximized_r7 ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](4, 9, maximized_r7 ? "viewportButton.minimizeLabel" : "viewportButton.maximizeLabel"))("icon", maximized_r7 ? "arrow-down-left-and-arrow-up-right-to-center" : "arrow-up-right-and-arrow-down-left-from-center"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](6, 11, "viewportButton.sCurveToSidebar"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](7, 13, "viewportButton.sCurveToSidebar")); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](5); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("showDetachButton", false)("isMaximized", ctx_r0.sCurveMaximized()); } } function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_11_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-cpr-workspace", 37); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("resizeStart", function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_11_Template_lib_cpr_workspace_resizeStart_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onResizeStart()); })("resizeEnd", function VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_11_Template_lib_cpr_workspace_resizeEnd_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r8); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onResizeEnd()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const viewportAxial_r9 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](2); const viewportSagittal_r10 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](4); const viewportCoronal_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](6); const viewportReformat_r12 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](8); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("axialTemplate", viewportAxial_r9)("cameraSliderTemplate", ctx_r0.cameraSliderTemplate())("coronalTemplate", viewportCoronal_r11)("reformatTemplate", viewportReformat_r12)("sagittalTemplate", viewportSagittal_r10)("isBlur", ctx_r0.isBlur())("isInitialViewportState", ctx_r0.isInitialViewportLayout())("lastSelectedMPRViewport", ctx_r0.lastSelectedMPRViewport())("selectedMPRViewport", ctx_r0.selectedMPRViewport()); } } function VolumeViewerComponent_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-viewport-layout-manager", 28); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("resizeStart", function VolumeViewerComponent_Conditional_1_Conditional_4_Template_lib_viewport_layout_manager_resizeStart_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onResizeStart()); })("resizeEnd", function VolumeViewerComponent_Conditional_1_Conditional_4_Template_lib_viewport_layout_manager_resizeEnd_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onResizeEnd()); })("loaderContextMenu", function VolumeViewerComponent_Conditional_1_Conditional_4_Template_lib_viewport_layout_manager_loaderContextMenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r4); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.toggleViewportContextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](1, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_1_Template, 1, 4, "ng-template", null, 10, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(3, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_3_Template, 1, 4, "ng-template", null, 11, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(5, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_5_Template, 1, 4, "ng-template", null, 12, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(7, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_7_Template, 1, 4, "ng-template", null, 13, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(9, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_9_Template, 11, 15, "ng-template", null, 14, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(11, VolumeViewerComponent_Conditional_1_Conditional_4_ng_template_11_Template, 1, 9, "ng-template", null, 15, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("viewportLayout", ctx_r0.viewportLayout())("focusedMPRViewport", ctx)("selectedMPRViewport", ctx_r0.selectedMPRViewport())("isInitialViewportState", ctx_r0.isInitialViewportLayout())("lastSelectedMPRViewport", ctx_r0.lastSelectedMPRViewport())("isBlur", ctx_r0.isBlur())("loadingProgress", ctx_r0.loadingProgress())("showSCurveGraph", ctx_r0.showSCurveGraph()); } } function VolumeViewerComponent_Conditional_1_ng_template_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](0, "lib-annotation-menu-item", 38); } if (rf & 2) { const item_r13 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("item", item_r13); } } function VolumeViewerComponent_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) { const _r14 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 26)(1, "lib-settings-popover", 39); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("visibilityChange", function VolumeViewerComponent_Conditional_1_Conditional_11_Template_lib_settings_popover_visibilityChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r14); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.active.set($event)); })("closed", function VolumeViewerComponent_Conditional_1_Conditional_11_Template_lib_settings_popover_closed_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r14); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.closeEditOrientation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](4, "lib-settings-popover", 40); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("visibilityChange", function VolumeViewerComponent_Conditional_1_Conditional_11_Template_lib_settings_popover_visibilityChange_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r14); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.active.set($event)); })("closed", function VolumeViewerComponent_Conditional_1_Conditional_11_Template_lib_settings_popover_closed_4_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r14); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.closeVolumeRenderPanel()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("showButton", false)("draggable", true)("dragBoundary", "[data-viewer-bounds]")("externalOpen", ctx_r0.viewerOrchestrator.isEditingOrientation())("formFieldConfig", ctx_r0.orientationFormConfig())("title", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 11, "annotationMenu.editOrientation.label"))("dragHandleAriaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](3, 13, "annotationMenu.editOrientation.move")); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("showButton", false)("externalOpen", ctx_r0.viewerOrchestrator.showVolumeRenderPanel())("formFieldConfig", ctx_r0.volumeRenderFormConfig())("title", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](5, 15, "volumeRenderingSettings.title")); } } function VolumeViewerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "section", 20); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("mouseup", function VolumeViewerComponent_Conditional_1_Template_section_mouseup_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.handleMouseUp($event)); })("mouseup", function VolumeViewerComponent_Conditional_1_Template_section_mouseup_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.handleWindowMouseUp()); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("mousemove", function VolumeViewerComponent_Conditional_1_Template_section_mousemove_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleGlobalMouseMove($event)); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("blur", function VolumeViewerComponent_Conditional_1_Template_section_blur_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.cancelInteractions()); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"]); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](1, "div", 21, 6); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("contextmenu", function VolumeViewerComponent_Conditional_1_Template_div_contextmenu_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onContextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](3, VolumeViewerComponent_Conditional_1_Conditional_3_Template, 2, 4, "div", 22); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](4, VolumeViewerComponent_Conditional_1_Conditional_4_Template, 13, 8, "lib-viewport-layout-manager", 23); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](5, "p-contextmenu", 24, 7); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("onShow", function VolumeViewerComponent_Conditional_1_Template_p_contextmenu_onShow_5_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); ctx_r0.active.set(false); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleMouseUp()); })("onHide", function VolumeViewerComponent_Conditional_1_Template_p_contextmenu_onHide_5_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.active.set(true)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](7, VolumeViewerComponent_Conditional_1_ng_template_7_Template, 1, 1, "ng-template", null, 8, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](9, "lib-annotation-menu", 25, 9); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](11, VolumeViewerComponent_Conditional_1_Conditional_11_Template, 6, 17, "div", 26); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_13_0; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵstyleProp"]("cursor", ctx_r0.interaction.viewportCursor()); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.hasMultiplePhases() ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"]((tmp_13_0 = ctx_r0.focusedMPRViewport()) ? 4 : -1, tmp_13_0); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("appendTo", "body")("model", ctx_r0.annotationMenuItems())("pt", ctx_r0.menuPt); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("model", ctx_r0.alignMenuItems()); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.seriesWindowState(ctx_r0.seriesUid()) ? 11 : -1); } } function VolumeViewerComponent_ng_template_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r15 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-viewport-button", 42); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("click", function VolumeViewerComponent_ng_template_2_Conditional_0_Template_lib_viewport_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r15); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.toggleVolumeRenderPanel()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](1, 2, "volumeRenderingSettings.buttonTooltip"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 4, "volumeRenderingSettings.buttonTooltip")); } } function VolumeViewerComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](0, VolumeViewerComponent_ng_template_2_Conditional_0_Template, 3, 6, "lib-viewport-button", 41); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.seriesWindowState(ctx_r0.seriesUid()) ? 0 : -1); } } function VolumeViewerComponent_ng_template_4_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r16 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-settings-popover", 44); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("visibilityChange", function VolumeViewerComponent_ng_template_4_Conditional_0_Template_lib_settings_popover_visibilityChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r16); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.active.set($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("formFieldConfig", ctx_r0.volumeRenderFormConfig())("buttonTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](1, 4, "volumeRenderingSettings.buttonTooltip"))("buttonAriaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 6, "volumeRenderingSettings.buttonTooltip"))("title", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](3, 8, "volumeRenderingSettings.title")); } } function VolumeViewerComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](0, VolumeViewerComponent_ng_template_4_Conditional_0_Template, 4, 10, "lib-settings-popover", 43); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.seriesWindowState(ctx_r0.seriesUid()) ? 0 : -1); } } function VolumeViewerComponent_ng_template_6_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r17 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-settings-popover", 46); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("visibilityChange", function VolumeViewerComponent_ng_template_6_Conditional_0_Template_lib_settings_popover_visibilityChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r17); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); ctx_r0.active.set($event); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.setCtSettingsVisible(!$event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("formFieldConfig", ctx_r0.ctFormConfig())("draggable", true)("dragBoundary", "[data-viewer-bounds]")("buttonTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](1, 7, "ctImageSettings.buttonTooltip"))("buttonAriaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 9, "ctImageSettings.label"))("title", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](3, 11, "ctImageSettings.title"))("dragHandleAriaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](4, 13, "ctImageSettings.move")); } } function VolumeViewerComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](0, VolumeViewerComponent_ng_template_6_Conditional_0_Template, 5, 15, "lib-settings-popover", 45); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.seriesWindowState(ctx_r0.seriesUid()) ? 0 : -1); } } function VolumeViewerComponent_ng_template_8_Template(rf, ctx) { if (rf & 1) { const _r18 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-viewport-button", 47); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("click", function VolumeViewerComponent_ng_template_8_Template_lib_viewport_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r18); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.toggleViewportContextMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("tooltip", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](1, 2, "viewportButton.settingsLabel"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 4, "viewportButton.settingsLabel")); } } function VolumeViewerComponent_ng_template_10_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r19 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "p-accordion", 49); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("valueChange", function VolumeViewerComponent_ng_template_10_Conditional_3_Template_p_accordion_valueChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r19); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onFloatingCardValueChange($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](1, "lib-annotation-card", 50); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("show", function VolumeViewerComponent_ng_template_10_Conditional_3_Template_lib_annotation_card_show_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r19); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const annotation_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreadContextLet"](2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onShowAnnotation(annotation_r20.id)); })("hide", function VolumeViewerComponent_ng_template_10_Conditional_3_Template_lib_annotation_card_hide_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r19); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const annotation_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreadContextLet"](2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onHideAnnotation(annotation_r20.id)); })("goTo", function VolumeViewerComponent_ng_template_10_Conditional_3_Template_lib_annotation_card_goTo_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r19); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const annotation_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreadContextLet"](2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onGoToAnnotation(annotation_r20.id)); })("updateName", function VolumeViewerComponent_ng_template_10_Conditional_3_Template_lib_annotation_card_updateName_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r19); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const annotation_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreadContextLet"](2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onUpdateAnnotationName($event, annotation_r20.id)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const moreActionsMenu_r21 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](1); const annotation_r20 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreadContextLet"](2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction0"](7, _c6))("multiple", true)("value", ctx_r0.floatingCardValue()); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("annotation", annotation_r20)("actions", annotation_r20.moreActions)("menuTrigger", moreActionsMenu_r21)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction2"](10, _c9, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction0"](8, _c7), _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction0"](9, _c8))); } } function VolumeViewerComponent_ng_template_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](0, "lib-annotation-menu", null, 16); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵdeclareLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](3, VolumeViewerComponent_ng_template_10_Conditional_3_Template, 2, 13, "p-accordion", 48); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](2); const annotation_r22 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵstoreLet"](ctx_r0.cardAnnotation()); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](annotation_r22 && !ctx_r0.viewerOrchestrator.isSettingsPanelOpen() ? 3 : -1); } } function VolumeViewerComponent_ng_template_12_Conditional_5_Template(rf, ctx) { if (rf & 1) { const _r25 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 55); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("mousedown", function VolumeViewerComponent_ng_template_12_Conditional_5_Template_div_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r25); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("wheel", function VolumeViewerComponent_ng_template_12_Conditional_5_Template_div_wheel_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r25); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](1, "lib-endo-dev-panel"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } } function VolumeViewerComponent_ng_template_12_Conditional_6_Template(rf, ctx) { if (rf & 1) { const _r26 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 55); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("mousedown", function VolumeViewerComponent_ng_template_12_Conditional_6_Template_div_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r26); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("wheel", function VolumeViewerComponent_ng_template_12_Conditional_6_Template_div_wheel_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r26); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](1, "lib-vascular-dev-panel"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } } function VolumeViewerComponent_ng_template_12_Conditional_7_Template(rf, ctx) { if (rf & 1) { const _r27 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 55); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("mousedown", function VolumeViewerComponent_ng_template_12_Conditional_7_Template_div_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r27); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); })("wheel", function VolumeViewerComponent_ng_template_12_Conditional_7_Template_div_wheel_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r27); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"]($event.stopPropagation()); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](1, "lib-render-quality-dev-panel"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } } function VolumeViewerComponent_ng_template_12_Conditional_8_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "div", 54); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](1, "div", 56); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } } function VolumeViewerComponent_ng_template_12_Template(rf, ctx) { if (rf & 1) { const _r23 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementStart"](0, "lib-volume-viewport", 51); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("viewportReady", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_viewportReady_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onViewportReady($event)); })("viewportDestroyed", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_viewportDestroyed_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.deregisterViewport($event)); })("perspectiveChange", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_perspectiveChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.viewerOrchestrator.updateIsPosterior($event)); })("mouseDown", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_mouseDown_0_listener($event) { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.handleViewportClick($event, id_r24)); })("mouseMove", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_mouseMove_0_listener($event) { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.handleViewportMouseMove($event, id_r24)); })("wheelScrolled", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_wheelScrolled_0_listener($event) { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleWheel($event, id_r24)); })("gestureStarted", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_gestureStarted_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleGestureStart($event)); })("gestureChanged", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_gestureChanged_0_listener($event) { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleGestureChange($event, id_r24)); })("gestureEnded", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_gestureEnded_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleGestureEnd()); })("contextMenu", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_contextMenu_0_listener($event) { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.interaction.handleContextMenu($event, id_r24)); })("toggleMaximizeViewport", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_toggleMaximizeViewport_0_listener() { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onToggleMaximizeViewport(id_r24)); })("focusedMPRViewportChange", function VolumeViewerComponent_ng_template_12_Template_lib_volume_viewport_focusedMPRViewportChange_0_listener() { const id_r24 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r23).$implicit; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r0.onFocusedMPRViewportSelect(id_r24)); }); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](4, "lib-viewport-overlay", 52); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](5, VolumeViewerComponent_ng_template_12_Conditional_5_Template, 2, 0, "div", 53); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](6, VolumeViewerComponent_ng_template_12_Conditional_6_Template, 2, 0, "div", 53); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](7, VolumeViewerComponent_ng_template_12_Conditional_7_Template, 2, 0, "div", 53); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](8, VolumeViewerComponent_ng_template_12_Conditional_8_Template, 2, 0, "div", 54); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelementEnd"](); } if (rf & 2) { const id_r24 = ctx.$implicit; const includeViewportSwap_r28 = ctx.includeViewportSwap; const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵnextContext"](); const volumeRenderTrigger_r29 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](3); const volumeRenderMaximized_r30 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](5); const ctPopoverSettings_r31 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](7); const viewportPopoverSettings_r32 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](9); const annotationCards_r33 = _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵreference"](11); const isMainMprViewport_r34 = ctx_r0.maximizedPanelId === id_r24 || ctx_r0.viewportIds.CORONAL === id_r24; _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("state", ctx_r0.getViewportStateById(id_r24))("darkMode", id_r24 !== ctx_r0.viewportIds.REFORMAT || ctx_r0.volumeIsDarkMode())("annotationCardsTemplate", isMainMprViewport_r34 && annotationCards_r33 || undefined)("settingsPopoverTemplate", isMainMprViewport_r34 && ctx_r0.viewportIds.REFORMAT !== id_r24 && ctPopoverSettings_r31 || ctx_r0.viewportIds.REFORMAT === id_r24 && ctx_r0.maximizedPanelId === id_r24 && volumeRenderMaximized_r30 || ctx_r0.viewportIds.REFORMAT === id_r24 && ctx_r0.maximizedPanelId !== id_r24 && volumeRenderTrigger_r29 || undefined)("viewportSettingsPopoverTemplate", viewportPopoverSettings_r32)("includeViewportSwap", includeViewportSwap_r28 && !ctx_r0.cprActive())("maximized", ctx_r0.isViewportMaximized(id_r24))("includeViewportMenu", id_r24 === ctx_r0.viewportIds.REFORMAT || ctx_r0.maximizedPanelId === id_r24)("angulation", ctx_r0.viewportAngulation(id_r24)())("createMode", ctx_r0.createMode())("cursor", ctx_r0.interaction.viewportCursor())("isPosterior", ctx_r0.isPosterior())("swapLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](1, 25, "viewportButton.swapLabel"))("minimizeLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](2, 27, "viewportButton.minimizeLabel"))("maximizeLabel", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpipeBind1"](3, 29, "viewportButton.maximizeLabel")); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("viewportId", id_r24)("viewportAxis", ctx_r0.viewportAxis(id_r24)())("cameraDetails", ctx_r0.viewportCameraState(id_r24)())("crosshairColors", ctx_r0.viewportAxisColors(id_r24))("crosshairRotation", ctx_r0.compactCrosshair(id_r24) ? 0 : ctx_r0.viewportCrosshairRotation(id_r24)())("compact", ctx_r0.compactCrosshair(id_r24)); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.showEndoDevPanel() && (id_r24 === ctx_r0.viewportIds.CORONAL && !ctx_r0.maximizedPanelId || ctx_r0.maximizedPanelId && id_r24 === ctx_r0.maximizedPanelId) ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.showVascularDevPanel() && (id_r24 === ctx_r0.viewportIds.CORONAL && !ctx_r0.maximizedPanelId || ctx_r0.maximizedPanelId && id_r24 === ctx_r0.maximizedPanelId) ? 6 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.showRenderQualityDevPanel() && (id_r24 === ctx_r0.viewportIds.CORONAL && !ctx_r0.maximizedPanelId || ctx_r0.maximizedPanelId && id_r24 === ctx_r0.maximizedPanelId) ? 7 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx_r0.viewerOrchestrator.vascularMaskComputing() && id_r24 === ctx_r0.viewportIds.REFORMAT ? 8 : -1); } } const REVALIDATE_MAX_ATTEMPTS = 3; const REVALIDATE_RETRY_DELAY_MS = 100; const POINTER_HEAL_SUPPRESS_MS = 1000; const MAXIMIZED_CROSSHAIR_COLOR = 'var(--p-app-viewport-maximized-crosshair)'; class VolumeViewerComponent { viewportIds = _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS; viewportIdsList = [_viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.AXIAL.valueOf(), _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.SAGITTAL.valueOf(), _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.REFORMAT.valueOf(), _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.CORONAL.valueOf()]; get ctSettingsButtonEl() { return document.querySelector(`#${_viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.CORONAL} lib-settings-popover lib-viewport-button`) ?? undefined; } ViewportAxis = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxis; PanelName = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.PanelName; log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_30__.getLogger)(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.VolumeViewportComponent.name); injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.EnvironmentInjector); windowService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_window_window_service__WEBPACK_IMPORTED_MODULE_33__.WindowService); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_14__.DialogService); viewerOrchestrator = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_volume_viewer_orchestrator_service__WEBPACK_IMPORTED_MODULE_47__.VolumeViewerOrchestrator); interaction = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_44__.ViewportInteractionService); renderingEngineService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_17__.RenderingEngineService); dicomDatabase = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_17__.DicomDatabaseService); annotationActors = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_annotation_actors_annotation_actors_service__WEBPACK_IMPORTED_MODULE_34__.AnnotationActorsService); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.AnnotationFacade); chamberFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.ChamberFacade); chamberService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_chamber_chamber_service__WEBPACK_IMPORTED_MODULE_28__.ChamberService); protocolCreation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_protocols__WEBPACK_IMPORTED_MODULE_31__.ProtocolCreationService); renderSettingsStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.renderSettingsStore); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.viewportStore); measurementService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.MeasurementService); menuTracker = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_annotation_menu_menu_tracker_service__WEBPACK_IMPORTED_MODULE_27__.MenuTrackerService); ctPopoverService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_ct_popover_service__WEBPACK_IMPORTED_MODULE_38__.CtPopoverService); volumeRenderingPopoverService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_volume_rendering_popover_service__WEBPACK_IMPORTED_MODULE_46__.VolumeRenderingPopoverService); cprService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_cpr_cpr_service__WEBPACK_IMPORTED_MODULE_37__.CprService); cprSession = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.cprSessionStore); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_12__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__.TranslateService); orientationFormRefresh = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(0, ...(ngDevMode ? [{ debugName: "orientationFormRefresh" }] : [])); uiFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_20__.UiFacade); volumeRenderFormConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "volumeRenderFormConfig" }] : [])); orientationFormConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "orientationFormConfig" }] : [])); ctFormConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "ctFormConfig" }] : [])); resizeIntervalId = undefined; resizeTimeoutId = undefined; revalidateTimeoutId = undefined; debouncedPointerHeal = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.debounce)(() => this.revalidateCanvasResolution(), POINTER_HEAL_SUPPRESS_MS, true); isWindowResizing = false; isSeriesResetting = false; destroyed = false; // Per-phase volume cache: each phase's volume is built lazily on first view and kept cached // for the rest of the session (all released together on series change/destroy) - switching // back and forth between phases is a common gated/multi-phase workflow, and evicting a // phase's volume the moment it's no longer active would force a full re-decode/re-upload on // every switch back to it. phaseVolumeIds = new Map(); // Volumes discardStaleVolume couldn't safely decache immediately because a series reset was // already in progress - drained once that reset's own resetForSeriesChange call has disabled // every viewport (see loadEffect).\ inFlightPhaseLoads = new Map(); pendingStaleVolumeDiscards = []; volumeIsDarkMode = this.renderSettingsStore.volumeIsDarkMode; seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)('', ...(ngDevMode ? [{ debugName: "seriesUid" }] : [])); studyUid = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "studyUid" }] : [])); storeUid = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "storeUid" }] : [])); otSeriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(undefined, ...(ngDevMode ? [{ debugName: "otSeriesUid" }] : [])); workSessionUid = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "workSessionUid" }] : [])); // When set, only these phases are offered and loaded. selectedPhaseIds = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(undefined, ...(ngDevMode ? [{ debugName: "selectedPhaseIds" }] : [])); layoutConfig = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "layoutConfig" }] : [])); viewportLayout = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "viewportLayout" }] : [])); focusedMPRViewport = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "focusedMPRViewport" }] : [])); selectedMPRViewport = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "selectedMPRViewport" }] : [])); isInitialViewportLayout = _angular_core__WEBPACK_IMPORTED_MODULE_2__.input.required(...(ngDevMode ? [{ debugName: "isInitialViewportLayout" }] : [])); lastSelectedMPRViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "lastSelectedMPRViewport" }] : [])); // The app page's camera slider, docked on the workspace's volume panel in CPR mode. cameraSliderTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(...(ngDevMode ? [undefined, { debugName: "cameraSliderTemplate" }] : [])); renderingEngineId = this.renderingEngineService.ENGINE_ID; selectedPhaseId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(undefined, ...(ngDevMode ? [{ debugName: "selectedPhaseId" }] : [])); isVolumeSwitching = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isVolumeSwitching" }] : [])); seriesPhases = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const uid = this.seriesUid(); return uid ? this.viewerOrchestrator.seriesPhases(uid) : []; }, ...(ngDevMode ? [{ debugName: "seriesPhases" }] : [])); availablePhases = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const phases = this.seriesPhases(); // Precedence: restored selection > pre-load modal > all. const stored = this.viewerOrchestrator.phaseSelection(this.seriesUid())?.availablePhaseIds; const selected = stored ?? this.selectedPhaseIds(); if (!selected || selected.length === 0) return phases; const selectedSet = new Set(selected); const filtered = phases.filter(phase => selectedSet.has(phase.id)); return filtered.length > 0 ? filtered : phases; }, ...(ngDevMode ? [{ debugName: "availablePhases" }] : [])); hasMultiplePhases = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.availablePhases().length > 1, ...(ngDevMode ? [{ debugName: "hasMultiplePhases" }] : [])); activePhaseInstanceUIDs = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const phaseId = this.selectedPhaseId(); const phase = this.availablePhases().find(p => p.id === phaseId); if (!phase) return []; return phase.imageIds.map(id => (0,_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_17__.parseImageId)(id).sopInstanceUID); }, ...(ngDevMode ? [{ debugName: "activePhaseInstanceUIDs" }] : [])); // Locale-independent phase label for DICOM export (e.g. "75%" or "120ms"). // Empty string for non-gated series or when no phase is selected. activePhaseLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { if (!this.isGated()) return ''; const phaseId = this.selectedPhaseId(); const phase = this.availablePhases().find(p => p.id === phaseId); const id = phase?.identification; if (!id) return ''; if (id.rrPercent !== undefined) return `${Math.round(id.rrPercent)}%`; if (id.triggerTime !== undefined) return `${id.triggerTime}ms`; return ''; }, ...(ngDevMode ? [{ debugName: "activePhaseLabel" }] : [])); /** Structured protocol metadata; unlike activePhaseLabel this is not presentation-only. */ activePhaseSelection = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const phaseId = this.selectedPhaseId(); const phase = this.availablePhases().find(candidate => candidate.id === phaseId); if (!phase) return; const id = phase.identification; if (id?.rrPercent !== undefined) { return { phaseId: phase.id, phaseUnit: 'percent', phaseValue: String(Math.round(id.rrPercent)) }; } if (id?.triggerTime !== undefined) { return { phaseId: phase.id, phaseUnit: 'milliseconds', phaseValue: String(id.triggerTime) }; } return { phaseId: phase.id, phaseUnit: 'unlabelled', phaseValue: 'unlabelled' }; }, ...(ngDevMode ? [{ debugName: "activePhaseSelection" }] : [])); switchToPhaseByLabel(label) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!label) return; const phase = _this.availablePhases().find(p => { const id = p.identification; if (!id) return false; if (id.rrPercent !== undefined) return `${Math.round(id.rrPercent)}%` === label; if (id.triggerTime !== undefined) return `${id.triggerTime}ms` === label; return false; }); if (phase) yield _this.onSelectVolume(phase.id); })(); } switchToPhaseById(phaseId) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this2.availablePhases().some(phase => phase.id === phaseId)) { yield _this2.onSelectVolume(phaseId); return true; } return false; })(); } captureViewportPreview(size = 128) { const ids = [_viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.AXIAL, _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.SAGITTAL, _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.CORONAL]; let canvas; for (const id of ids) { const vp = this.renderingEngineService.getViewport(id.valueOf()); if (vp?.canvas) { canvas = vp.canvas; break; } } if (!canvas) return undefined; try { const offscreen = new OffscreenCanvas(size, size); const context = offscreen.getContext('2d'); if (!context) return undefined; context.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, size, size); const { data } = context.getImageData(0, 0, size, size); const rgb = new Uint8Array(size * size * 3); for (let rgbaOffset = 0, rgbOffset = 0; rgbaOffset < data.length; rgbaOffset += 4, rgbOffset += 3) { rgb[rgbOffset] = data[rgbaOffset] ?? 0; rgb[rgbOffset + 1] = data[rgbaOffset + 1] ?? 0; rgb[rgbOffset + 2] = data[rgbaOffset + 2] ?? 0; } return rgb; } catch { return undefined; } } // Gated (cardiac) when any offered phase carries identification → "Phase"; else "Volume". isGated = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.availablePhases().some(phase => phase.identification !== undefined), ...(ngDevMode ? [{ debugName: "isGated" }] : [])); // instant() is not reactive; recompute once the language file arrives or the language changes. langChange = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__.toSignal)(this.translate.onLangChange); volumeWord = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { this.langChange(); return this.translate.instant(this.isGated() ? 'multiphase.phase' : 'multiphase.volume'); }, ...(ngDevMode ? [{ debugName: "volumeWord" }] : [])); phaseSelectOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const word = this.volumeWord(); const triggerUnit = this.translate.instant('multiphase.triggerUnit'); return this.availablePhases().map(phase => { const base = `${word} ${phase.label}`; const detail = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.formatPhaseIdentification)(phase.identification, { triggerUnit }); return { label: detail ? `${base}: ${detail}` : base, value: phase.id }; }); }, ...(ngDevMode ? [{ debugName: "phaseSelectOptions" }] : [])); toggleMaximizeViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); focusedMPRViewportChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); selectedMPRViewportChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); escPressed = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.output)(); isBlur = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(false, ...(ngDevMode ? [{ debugName: "isBlur" }] : [])); maximizedPanelId = undefined; focusedMPRViewportId = _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.CORONAL; selectedMPRViewportId = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportName.CORONAL; lastSelectedMPRViewportId = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportName.CORONAL; initialViewportLayout = false; studySeriesKey = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const studyUid = this.studyUid(); const seriesUid = this.seriesUid(); return `${studyUid}::${seriesUid}`; }, ...(ngDevMode ? [{ debugName: "studySeriesKey" }] : [])); seriesUid$ = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__.toObservable)(this.seriesUid); storeUid$ = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__.toObservable)(this.storeUid); emptySeriesCacheProgress = { cachedCount: 0, percent: 0, totalCount: 0 }; seriesCacheProgressSubscription; seriesCacheProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(this.emptySeriesCacheProgress, ...(ngDevMode ? [{ debugName: "seriesCacheProgress" }] : [])); loadingProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const cache = this.seriesCacheProgress(); const loading = this.viewerOrchestrator.status() === 'loading' || this.viewerOrchestrator.isCachingSource(); return { ...cache, loading }; }, ...(ngDevMode ? [{ debugName: "loadingProgress" }] : [])); annotationMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)([], ...(ngDevMode ? [{ debugName: "annotationMenuItems" }] : [])); annotationMenuItemService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_annotation_menu_annotation_menu_item_service__WEBPACK_IMPORTED_MODULE_24__.AnnotationMenuItemService); ctxMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)('ctxMenu', ...(ngDevMode ? [{ debugName: "ctxMenu" }] : [])); alignMenu = _angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild.required('alignMenu'); // Only stamped while the CPR layout is rendered; it owns the carrier mounts. cprWorkspace = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.viewChild)(_cpr_cpr_workspace_component__WEBPACK_IMPORTED_MODULE_36__.CprWorkspaceComponent, ...(ngDevMode ? [{ debugName: "cprWorkspace" }] : [])); layoutBeforeCpr = undefined; cprActive = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.cprService.desiredLayout() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.CPR, ...(ngDevMode ? [{ debugName: "cprActive" }] : [])); // Derived from the authoritative viewportLayout input rather than maximizedPanelId, so it // stays correct regardless of which entry point maximized the s-curve view (the grid-tile's // own maximize button, or the shortcut from the sidebar drawer, which never touches // maximizedPanelId since that's only set by this component's own onToggleMaximizeViewport). sCurveMaximized = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.viewportLayout() === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_S_CURVE, ...(ngDevMode ? [{ debugName: "sCurveMaximized" }] : [])); /** True for the app-level maximize outside CPR, and for the workspace's own inside it. */ isViewportMaximized(viewportId) { if (!this.cprActive()) return this.maximizedPanelId === viewportId; // Unmapped viewports (the hidden MPRs) must not match an unset maximized panel. const panel = _cpr_cpr_config__WEBPACK_IMPORTED_MODULE_35__.CPR_PANEL_BY_VIEWPORT_ID[viewportId]; return panel !== undefined && this.cprSession.maximizedPanel() === panel; } freezeShortAxis() { this.cprWorkspace()?.freezeShortAxis(); } unfreezeShortAxis() { this.cprWorkspace()?.unfreezeShortAxis(); } interactionModeService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_interaction_mode_interaction_mode_service__WEBPACK_IMPORTED_MODULE_29__.InteractionModeService); interactionMode = this.interactionModeService.interactionMode; createMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.annotationFacade.annotationBeingCreated() !== undefined, ...(ngDevMode ? [{ debugName: "createMode" }] : [])); cardAnnotation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const selected = this.selectedAnnotations(); if (selected.length > 1) return; return selected[0]; }, ...(ngDevMode ? [{ debugName: "cardAnnotation" }] : [])); floatingCardOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(true, ...(ngDevMode ? [{ debugName: "floatingCardOpen" }] : [])); floatingCardValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const annotation = this.cardAnnotation(); return this.floatingCardOpen() && annotation ? [annotation.id] : []; }, ...(ngDevMode ? [{ debugName: "floatingCardValue" }] : [])); onFloatingCardValueChange(value) { this.floatingCardOpen.set(Array.isArray(value) ? value.length > 0 : value !== null && value !== undefined); } volumeIds; // When active is false, viewports will have their interactivity disabled. // This is currently used to prevent unwanted interaction while a context menu is open. active = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(true, ...(ngDevMode ? [{ debugName: "active" }] : [])); showSCurveGraph = this.uiFacade.sCurveGraphDetached; menuPt = { root: { // Prevents being able to right-click an open menu and open the native menu oncontextmenu(event) { event.preventDefault(); }, style: { position: 'fixed' } }, submenu: 'min-w-max' }; handleKeyDown(event) { if (this.menuTracker.closeTopMenu()) { return; } // Check if a dialog is open, and handle that first. Take the last one in case there is a stack of open dialogs const dialogReference = [...this.dialogService.dialogComponentRefMap.values()].at(-1); if (dialogReference) { dialogReference.instance.close(); return; } event.stopPropagation(); event.preventDefault(); if (this.cprSession.editState() === 'editing') { this.cprService.cancelEdit(); return; } if (this.protocolCreation.cancelCurrentStep()) { return; } switch (this.interactionMode().type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.ADD_POINTS: { this.interactionModeService.clearMode(); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.CREATE: { this.protocolCreation.stop(); this.annotationFacade.cancelAnnotationCreation(); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.SELECT: { this.escPressed.emit(); break; } } } handleEnterKey(event) { if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.isEditableTarget)(event.target)) return; const interactionMode = this.interactionMode(); // Adding points to an already-finished spline - there's nothing to validate (the // annotation was already complete before this mode started), so just exit it, same // as Escape does for this mode. if (interactionMode.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.ADD_POINTS) { event.preventDefault(); this.interactionModeService.clearMode(); return; } if (interactionMode.type !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.CREATE) return; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_18__.annotationIsSpline)(interactionMode.annotation)) return; event.preventDefault(); this.interaction.completeAnnotationCreationIfValid(interactionMode.annotation); } handleDeleteKey(event) { if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.isEditableTarget)(event.target)) return; // The spline being edited is normally the selected annotation, so this would delete the // very thing the reformation is showing. if (this.cprSession.editState() === 'editing') return; const selectedIds = this.annotationFacade.selectedIds(); if (selectedIds.length === 0) return; event.stopPropagation(); event.preventDefault(); this.annotationMenuItemService.confirmDeleteSelectedAnnotations(event.target); } constructor() { var _this3 = this; const fullscreenEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.windowService.isFullscreen(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => this.annotationFacade.cancelAnnotationCreation()); }, ...(ngDevMode ? [{ debugName: "fullscreenEffect" }] : [])); // NOTE: For an unknown reason, the 3d volume doesn't properly // display when switching tabs until interacting. // This small effect can fix that issue until we figure out the cause. const workSessionChangeEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.workSessionUid(); setTimeout(() => { this.viewerOrchestrator.forceRerender(); }, 10); }, ...(ngDevMode ? [{ debugName: "workSessionChangeEffect" }] : [])); const annotationScaleEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.viewerOrchestrator.annotationScaleCacheBuster(); this.annotationActors.refreshForViewportScaleChange(); }, ...(ngDevMode ? [{ debugName: "annotationScaleEffect" }] : [])); const loadEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.studySeriesKey(); // Trigger effect when study/series changes (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this3.isSeriesResetting = true; _this3.volumeIds = undefined; _this3.selectedPhaseId.set(undefined); _this3.isVolumeSwitching.set(false); _this3.cprService.activeVolumeId.set(undefined); _this3.annotationActors.setViewports([]); _this3.annotationFacade.clearAnnotations(); _this3.chamberFacade.clearChambers(); try { yield _this3.viewerOrchestrator.resetForSeriesChange(); // Only decache once resetForSeriesChange has disabled every viewport - decaching // first would drop a volume's data while a viewport actor could still be bound to // it mid-render. for (const volumeIds of _this3.phaseVolumeIds.values()) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); } _this3.phaseVolumeIds.clear(); for (const volumeIds of _this3.pendingStaleVolumeDiscards) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); } _this3.pendingStaleVolumeDiscards.length = 0; } finally { _this3.isSeriesResetting = false; } _this3.setup(); })); }, ...(ngDevMode ? [{ debugName: "loadEffect" }] : [])); // Bridge CprService's requested layout to the app via the maximize channel. const cprLayoutEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { const desired = this.cprService.desiredLayout(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => { if (desired === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.CPR) { this.layoutBeforeCpr = this.viewportLayout(); this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.CPR); return; } if (this.layoutBeforeCpr !== undefined) { this.toggleMaximizeViewport.emit(this.layoutBeforeCpr); this.layoutBeforeCpr = undefined; } }); }, ...(ngDevMode ? [{ debugName: "cprLayoutEffect" }] : [])); this.openContextMenuSubscriber(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef).onDestroy(() => { fullscreenEffect.destroy(); workSessionChangeEffect.destroy(); annotationScaleEffect.destroy(); loadEffect.destroy(); cprLayoutEffect.destroy(); }); } captureChamberFromCurrentView() { this.chamberService.createNewChamber({ angulation: this.viewportAngulation(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.MIDDLEMAIN)(), ax: this.viewportStore.ax(), crosshairRotation: this.viewportCrosshairRotation(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.MIDDLEMAIN)(), intersection: this.viewportStore.intersection(), isocenter: this.viewportStore.isocenter(), isPosterior: this.isPosterior() }); } viewportEffectReady = false; initViewportEffect() { if (this.viewportEffectReady) return; const initEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { const toInit = this.viewerOrchestrator.viewportsToEnable(); if (toInit.length > 0) { this.setup(); } }, ...(ngDevMode ? [{ debugName: "initEffect" }] : [])); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef).onDestroy(() => { initEffect.destroy(); }); this.viewportEffectReady = true; } volumeRequestEffectReady = false; initVolumeRequestEffect() { if (this.volumeRequestEffectReady) return; const requestEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { const request = this.viewerOrchestrator.requestedActiveVolume(); if (!request) return; (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => { this.viewerOrchestrator.clearRequestedActiveVolume(); this.handleVolumeRequest(request).catch(error => this.log.error('Failed to handle volume request', error)); }); }, ...(ngDevMode ? [{ debugName: "requestEffect" }] : [])); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef).onDestroy(() => { requestEffect.destroy(); }); this.volumeRequestEffectReady = true; } handleVolumeRequest(request) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (request.phaseId !== _this4.selectedPhaseId()) { yield _this4.onSelectVolume(request.phaseId); } if (_this4.destroyed) return; if (request.revealAnnotationId) { _this4.annotationFacade.selectAnnotations([request.revealAnnotationId]); _this4.viewerOrchestrator.moveCrosshairToAnnotation(request.revealAnnotationId); } if (request.revealChamberId) { _this4.chamberFacade.selectChambers([request.revealChamberId]); } })(); } // We don't initialize these effects until the volume has been loaded formEffectsReady = false; initFormEffects() { if (this.formEffectsReady) return; const ctFormUpdateEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { // Don't need the value, just need to trigger when change this.renderSettingsStore.windowSettings.name(); const seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => this.seriesUid()); // Also track seriesWindowState so the effect re-fires once loadSeries populates it. // Guard: skip until window state is ready to avoid a premature call. if (!this.viewerOrchestrator.seriesWindowState(seriesUid)) return; this.ctPopoverService.seriesUid.set(seriesUid); this.ctFormConfig.set(this.ctPopoverService.getCtFormConfig()); }, ...(ngDevMode ? [{ debugName: "ctFormUpdateEffect" }] : [])); const volumeFormUpdateEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.renderSettingsStore.volumeSettings(); this.viewerOrchestrator.vascularSegmentationState(); this.viewerOrchestrator.vascularMaskComputing(); const seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => this.seriesUid()); this.volumeRenderingPopoverService.seriesUid.set(seriesUid); this.volumeRenderFormConfig.set((0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => this.volumeRenderingPopoverService.getVolumeRenderingFormConfig())); }, ...(ngDevMode ? [{ debugName: "volumeFormUpdateEffect" }] : [])); const orientationFormUpdateEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.effect)(() => { this.viewerOrchestrator.editOrientationTargetId(); this.orientationFormRefresh(); this.orientationFormConfig.set((0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => { const sliders = (0,_orientation_form_config__WEBPACK_IMPORTED_MODULE_40__.buildOrientationFormConfig)(() => this.editOrientationTarget(), annotation => this.annotationFacade.updateAnnotation(annotation), () => this.viewerOrchestrator.decrease3dViewportImageQuality(), () => this.viewerOrchestrator.increase3dViewportImageQuality()); if (sliders.length === 0) return sliders; const alignWithField = { defaultValue: '', icon: 'align-horizontal-center', label: 'annotationMenu.alignWith', name: 'alignWith', onTrigger: event => this.alignMenu().show(event), type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.SettingsPopoverField.MENU_BUTTON }; return [alignWithField, ...sliders]; })); }, ...(ngDevMode ? [{ debugName: "orientationFormUpdateEffect" }] : [])); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef).onDestroy(() => { ctFormUpdateEffect.destroy(); volumeFormUpdateEffect.destroy(); orientationFormUpdateEffect.destroy(); }); this.formEffectsReady = true; } editOrientationTarget() { const id = this.viewerOrchestrator.editOrientationTargetId(); if (!id) return undefined; const annotation = this.annotationFacade.getAnnotationById(id); return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_18__.annotationIsObject3D)(annotation) ? annotation : undefined; } alignMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { const target = this.editOrientationTarget(); if (!target) return []; return this.annotationMenuItemService.alignWithItems(target, () => this.orientationFormRefresh.update(tick => tick + 1)); }, ...(ngDevMode ? [{ debugName: "alignMenuItems" }] : [])); readyToSetup = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => !!this.studyUid() && !!this.seriesUid() && this.layoutConfig().length === this.viewportStates().length, ...(ngDevMode ? [{ debugName: "readyToSetup" }] : [])); viewportStates = this.viewerOrchestrator.viewportStates; ngOnInit() { this.ctPopoverService.seriesUid.set(this.seriesUid()); this.volumeRenderingPopoverService.seriesUid.set(this.seriesUid()); this.seriesCacheProgressSubscription = (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.combineLatest)([this.seriesUid$, this.storeUid$]).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_9__.switchMap)(([seriesUid, storeUid]) => { if (!seriesUid || !storeUid) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.of)(this.emptySeriesCacheProgress); } return this.viewerOrchestrator.streamSeriesCacheProgress(seriesUid, storeUid); })).subscribe(progress => { this.seriesCacheProgress.set(progress); }); } onViewportReady(event) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this5.viewerOrchestrator.registerViewport(event.element, event.options, _this5.seriesUid()); _this5.viewerOrchestrator.forceRerender(); })(); } ngAfterViewInit() { this.setup(); } initVolume() { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // Only have to loadSeries once, not between layout changes if (_this6.volumeIds !== undefined) return; const initSeriesKey = _this6.studySeriesKey(); // Reopen must read the restored selection before loadSeries, else prefetch re-downloads // deselected phases. yield _this6.viewerOrchestrator.whenWorkSessionLoaded(); if (_this6.destroyed) return; const restoredSelection = _this6.viewerOrchestrator.phaseSelection(_this6.seriesUid())?.availablePhaseIds; const selectedPhaseIds = restoredSelection ?? _this6.selectedPhaseIds(); const imageIds = yield _this6.viewerOrchestrator.loadSeries(_this6.seriesUid(), _this6.studyUid(), _this6.storeUid(), selectedPhaseIds); if (_this6.viewerOrchestrator.wasSeriesUnseparable(_this6.seriesUid(), _this6.studyUid(), _this6.storeUid())) { _this6.messageService.add({ detail: _this6.translate.instant('unseparablePhases.detail'), severity: 'warn', summary: _this6.translate.instant('unseparablePhases.summary') }); } // A volume built from the flattened image set would mix phases that share slice positions into // an invalid volume, so exactly one phase is opened. const phases = _this6.availablePhases(); const restoredActiveId = _this6.viewerOrchestrator.phaseSelection(_this6.seriesUid())?.activePhaseId; const activePhase = phases.find(phase => phase.id === restoredActiveId) ?? phases[0]; const phaseId = activePhase?.id ?? 'default:0'; _this6.selectedPhaseId.set(phaseId); // Persist the resolved selection so a fresh open is captured by the work-session auto-save. _this6.viewerOrchestrator.setPhaseSelection(_this6.seriesUid(), phases.map(phase => phase.id), phaseId); let volumeIds; try { volumeIds = yield _this6.loadPhaseVolume(phaseId, activePhase?.imageIds ?? imageIds); } catch (error) { if (!_this6.isStaleLoad(initSeriesKey)) { _this6.viewerOrchestrator.reportVolumeLoadError(error); } return; } if (_this6.isStaleLoad(initSeriesKey)) { _this6.discardStaleVolume(phaseId, volumeIds); return; } _this6.volumeIds = volumeIds; _this6.cprService.activeVolumeId.set(_this6.volumeIds.mprVolumeId); _this6.measurementService.updateVolume(_this6.volumeIds.mprVolumeId); _this6.viewerOrchestrator.setVolumeCenter(_this6.volumeIds.mprVolumeId); _this6.warmPhaseVolumesInBackground(initSeriesKey, phaseId); })(); } warmPhaseVolumesInBackground(seriesKey, activePhaseId) { var _this7 = this; const phases = this.availablePhases(); const activeIndex = phases.findIndex(phase => phase.id === activePhaseId); // 1) Eagerly warm the next likely phase immediately. const likelyNext = activeIndex !== -1 && activeIndex + 1 < phases.length ? phases[activeIndex + 1] : undefined; if (likelyNext && !this.phaseVolumeIds.has(likelyNext.id)) { queueMicrotask(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this7.destroyed || _this7.isStaleLoad(seriesKey)) return; try { yield _this7.loadPhaseVolume(likelyNext.id, likelyNext.imageIds); } catch { // best-effort } })); } // 2) Warm remaining phases during idle time. const idle = globalThis.requestIdleCallback ?? (callback => globalThis.setTimeout(() => callback({ didTimeout: true, timeRemaining: () => 0 }), 50)); idle(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this7.destroyed || _this7.isStaleLoad(seriesKey)) return; for (const phase of phases) { if (phase.id === activePhaseId) continue; if (likelyNext && phase.id === likelyNext.id) continue; if (_this7.destroyed || _this7.isStaleLoad(seriesKey)) return; if (_this7.phaseVolumeIds.has(phase.id)) continue; try { yield _this7.loadPhaseVolume(phase.id, phase.imageIds); } catch { // best-effort } } }), // start soon on busy main thread { timeout: 300 }); } loadPhaseVolume(phaseId, imageIds) { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const seriesKey = _this8.studySeriesKey(); const cacheKey = `${seriesKey}::${phaseId}`; const cached = _this8.phaseVolumeIds.get(cacheKey); if (cached) return cached; const inFlight = _this8.inFlightPhaseLoads.get(cacheKey); if (inFlight) return inFlight; const loadPromise = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.loadVolumeImages)(imageIds, `${_this8.seriesUid()}-${phaseId}`).then(volumeIds => { // Only cache if still relevant (series hasn't changed) if (_this8.studySeriesKey() === seriesKey && !_this8.destroyed) { _this8.phaseVolumeIds.set(cacheKey, volumeIds); return volumeIds; } else { // Stale load - decache immediately (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); throw new Error('Series changed during load'); } }).finally(() => { _this8.inFlightPhaseLoads.delete(cacheKey); }); _this8.inFlightPhaseLoads.set(cacheKey, loadPromise); return loadPromise; })(); } /** * Whether a load captured under `capturedSeriesKey` is no longer relevant to apply - the * series was destroyed, reset, or changed to a different one while the load was in flight. */ isStaleLoad(capturedSeriesKey) { return this.destroyed || this.isSeriesResetting || this.studySeriesKey() !== capturedSeriesKey; } /** * loadPhaseVolume caches into phaseVolumeIds as soon as it resolves, before its caller gets a * chance to notice the series has already moved on - release it here instead of leaking it in * Cornerstone's cache for the rest of the session. */ discardStaleVolume(phaseId, volumeIds) { const seriesKey = this.studySeriesKey(); const cacheKey = `${seriesKey}::${phaseId}`; if (this.phaseVolumeIds.get(cacheKey) === volumeIds) { this.phaseVolumeIds.delete(cacheKey); } if (this.isSeriesResetting) { // A series reset is already tearing down viewports concurrently - decaching now could // drop this volume's data while it's still bound to one mid-render. Defer to the reset's // own cleanup, which only runs after resetForSeriesChange has disabled every viewport. this.pendingStaleVolumeDiscards.push(volumeIds); return; } (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); } onSelectVolume(phaseId) { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (phaseId === _this9.selectedPhaseId() || _this9.isVolumeSwitching()) return; const availablePhases = _this9.availablePhases(); const phase = availablePhases.find(candidate => candidate.id === phaseId); if (!phase) return; const previousPhaseId = _this9.selectedPhaseId(); const switchSeriesKey = _this9.studySeriesKey(); const cancelled = _this9.protocolCreation.cancelCurrentStep(); if (!cancelled) { _this9.annotationFacade.cancelAnnotationCreation(); } _this9.isVolumeSwitching.set(true); try { const volumeIds = yield _this9.loadPhaseVolume(phase.id, phase.imageIds); if (_this9.isStaleLoad(switchSeriesKey)) { _this9.discardStaleVolume(phase.id, volumeIds); return; } yield _this9.viewerOrchestrator.setActiveVolume(volumeIds); if (_this9.isStaleLoad(switchSeriesKey)) { _this9.discardStaleVolume(phase.id, volumeIds); return; } _this9.volumeIds = volumeIds; _this9.cprService.activeVolumeId.set(volumeIds.mprVolumeId); _this9.measurementService.updateVolume(volumeIds.mprVolumeId); _this9.viewerOrchestrator.setVolumeCenter(volumeIds.mprVolumeId); _this9.selectedPhaseId.set(phase.id); _this9.viewerOrchestrator.setPhaseSelection(_this9.seriesUid(), availablePhases.map(candidate => candidate.id), phase.id); // Persist the outgoing bundle and mirror the incoming one into the stores before rendering. if (previousPhaseId !== undefined) { _this9.viewerOrchestrator.switchActiveVolume(previousPhaseId, phase.id); } // Preset must be applied before forceRerender, else renderAll() flashes a stale, MPR-looking frame. _this9.viewerOrchestrator.reapplyVolumeRenderSettings(); _this9.viewerOrchestrator.renderStoredCameras(); _this9.viewerOrchestrator.forceRerender(); } catch (error) { if (!_this9.isStaleLoad(switchSeriesKey)) { _this9.viewerOrchestrator.reportVolumeLoadError(error); } } finally { _this9.isVolumeSwitching.set(false); } })(); } setup() { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this0.isSeriesResetting) return; if (!_this0.readyToSetup()) return; const viewportConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.untracked)(() => _this0.viewerOrchestrator.viewportsToEnable()); const firstLoad = _this0.volumeIds === undefined; if (firstLoad) { yield _this0.initVolume(); } if (_this0.volumeIds === undefined) { return; } _this0.viewerOrchestrator.resetCameraRendered(); const enabledIds = yield _this0.viewerOrchestrator.enableViewports(viewportConfig, _this0.volumeIds); // Load may outlast the component; bail before touching the injector. if (_this0.destroyed) return; (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.runInInjectionContext)(_this0.injector, () => { _this0.initFormEffects(); _this0.viewerOrchestrator.initEffects(); _this0.annotationActors.initEffects(); _this0.initViewportEffect(); _this0.initVolumeRequestEffect(); }); _this0.viewerOrchestrator.forceRerender(); // Without this, layout changes can show stale viewports // CPR carriers must not receive MPR-space annotation actors — they'd paint over the ribbon. _this0.annotationActors.setViewports(_this0.renderingEngineService.getActiveViewports().filter(viewport => !(0,_cpr_cpr_config__WEBPACK_IMPORTED_MODULE_35__.isCprCarrierViewportId)(viewport.id))); _this0.viewerOrchestrator.completeViewports(enabledIds); })(); } onShowAnnotation(annotationId) { this.annotationMenuItemService.showAnnotation(annotationId); } onHideAnnotation(annotationId) { this.annotationMenuItemService.hideAnnotation(annotationId); } onGoToAnnotation(annotationId) { this.annotationMenuItemService.goToAnnotation(annotationId); } onUpdateAnnotationName(newName, annotationId) { this.annotationMenuItemService.updateAnnotationName(annotationId, newName); } selectedAnnotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => { return this.annotationFacade.selectedAnnotationsWithMeasurements().map(annotation => { const menuItems = this.annotationMenuItemService.menuItemsForAnnotation(annotation); const contentMenuItems = menuItems.filter(({ includeInCard }) => includeInCard); return { ...annotation, contentMenuItems, moreActions: menuItems }; }); }, ...(ngDevMode ? [{ debugName: "selectedAnnotations" }] : [])); getViewportStateById(viewportId) { const initialConfig = this.layoutConfig().find(({ id }) => id === viewportId); if (!initialConfig) { throw new Error(`Configuration not found for viewport ID: ${viewportId}. Check VIEWPORT_LAYOUT_CONFIG.`); } return initialConfig; } isPosterior = this.viewportStore.isPosterior; handleViewportClick(event, viewportId) { this.viewerOrchestrator.closeEndoDevPanel(); this.viewerOrchestrator.closeVascularDevPanel(); this.viewerOrchestrator.closeRenderQualityDevPanel(); const clickResult = this.interaction.handleViewportMouseDown(event, viewportId); if (!clickResult) return; const { isDoubleClick } = clickResult; const interactionMode = this.interactionMode(); switch (interactionMode.type) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.ADD_POINTS: { this.interaction.handleAddPointClick(viewportId, interactionMode.annotationId, isDoubleClick); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.CREATE: { this.interaction.handleAnnotationCreationClick(viewportId, interactionMode.annotation, isDoubleClick); break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.InteractionModeType.SELECT: { if (isDoubleClick) { this.onToggleMaximizeViewport(viewportId); } const isMultiselect = event.ctrlKey || event.shiftKey; const details = this.interaction.handleAnnotationSelectionClick(viewportId, isMultiselect); if (details) { this.cprService.snapCursorToSpline(details, viewportId, [event.offsetX, event.offsetY]); } break; } } } onToggleMaximizeViewport(viewportId) { if (this.cprActive()) { // Workspace-internal maximize: a grid re-flow, never `LayoutType.MAXIMIZE_*`, which // would re-stamp the templates and orphan the session. const panel = _cpr_cpr_config__WEBPACK_IMPORTED_MODULE_35__.CPR_PANEL_BY_VIEWPORT_ID[viewportId]; if (panel) this.cprSession.toggleMaximizedPanel(panel); return; } if (this.viewportLayout() !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.DEFAULT) { this.setDefaultViewportLayout(); return; } switch (viewportId) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.PanelName.S_CURVE_GRAPH: { this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_S_CURVE); break; } case _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.AXIAL: { this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_AXIAL); break; } case _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.CORONAL: { this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_CORONAL); break; } case _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.REFORMAT: { this.refreshVolumeRenderFormConfig(); this.viewerOrchestrator.setReformatMaximized(true); this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_3D); break; } case _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.SAGITTAL: { this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.MAXIMIZE_SAGITTAL); break; } default: { this.log.error(`Unknown viewport ID: ${viewportId}. Cannot toggle maximize.`); return; } } this.maximizedPanelId = viewportId; } setDefaultViewportLayout() { if (this.maximizedPanelId === _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.REFORMAT) { this.refreshVolumeRenderFormConfig(); this.viewerOrchestrator.setReformatMaximized(false); } // Maximized and detached are independent states (TVC-1238) - this must not touch // uiFacade's detached flag; the sidebar panel hides its own s-curve copy purely from // isMaximized (see SCurvePanelComponent.showGraph), so whatever detached state the graph // had before maximizing is exactly what it returns to here. this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.DEFAULT); this.maximizedPanelId = undefined; } refreshVolumeRenderFormConfig() { this.volumeRenderFormConfig.set(this.volumeRenderingPopoverService.getVolumeRenderingFormConfig()); } onFocusedMPRViewportSelect(viewportId) { this.lastSelectedMPRViewportId = this.selectedMPRViewportId; this.focusedMPRViewportId = viewportId; if (viewportId === _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.REFORMAT) { this.log.warn('Cannot swap viewport in focus for 3D/Reformat viewport.'); return; } this.viewportStore.swapViewportAxis(viewportId); // Cornerstone's MPR viewport doesn't settle its slice state after a 90° camera flip. // Nudging the angulation by ±0.1° triggers two full camera-effect cycles which // forces both viewports to re-initialise their image planes cleanly. this.viewportStore.nudgeAngulationsToForceResettle(); } onResizeStart() { // Capture the short-axis's correct frame before resetCameraForResize zooms it. this.freezeShortAxis(); this.isBlur.set(true); this.renderingEngineService.resetCameraForResize(); // Clear any existing interval (safety check) clearInterval(this.resizeIntervalId); //Call resetCameraForResize every 1ms during resize - this avoids jellification of viewports this.resizeIntervalId = setInterval(() => this.healViewportCameras(), 1); } /** Resizes the engine, then re-fixes the CPR camera windows. */ healViewportCameras() { this.renderingEngineService.resetCameraForResize(); this.cprService.refreshShortAxisCamera(); this.cprService.refreshLongAxisCamera(); this.viewerOrchestrator.forceRerender(); } onResizeEnd() { // Clear the interval when resize ends if (this.resizeIntervalId !== undefined) { clearInterval(this.resizeIntervalId); this.resizeIntervalId = undefined; } // Clear any pending resize timeout if (this.resizeTimeoutId !== undefined) { clearTimeout(this.resizeTimeoutId); this.resizeTimeoutId = undefined; } setTimeout(() => { this.renderingEngineService.resetCameraForResize(); this.viewerOrchestrator.forceRerender(); this.revealCorrectedShortAxis(); }, 200); } // Re-impose the short-axis FOV, un-blur, then drop the frozen still one frame // later — so the corrected live render has painted before it's revealed. revealCorrectedShortAxis() { requestAnimationFrame(() => { this.cprService.refreshShortAxisCamera(); this.cprService.refreshLongAxisCamera(); requestAnimationFrame(() => { this.cprService.refreshShortAxisCamera(); this.cprService.refreshLongAxisCamera(); this.isBlur.set(false); requestAnimationFrame(() => this.unfreezeShortAxis()); }); }); } onWindowResize() { // If this is the first resize event, call onResizeStart if (!this.isWindowResizing) { this.isWindowResizing = true; this.onResizeStart(); } // Clear any existing timeout if (this.resizeTimeoutId !== undefined) { clearTimeout(this.resizeTimeoutId); } // Set a timeout to detect when resize ends (debounce) this.resizeTimeoutId = setTimeout(() => { this.isWindowResizing = false; this.onResizeEnd(); this.resizeTimeoutId = undefined; }, 150); } /** Handles a canvas-resolution mismatch after a devicePixelRatio change that produced no usable * `resize` (OS scale change, move to a differently-scaled monitor). * * Retries because Cornerstone silently drops a resize while a render is pending. */ revalidateCanvasResolution(attempt = 0) { clearTimeout(this.revalidateTimeoutId); this.revalidateTimeoutId = undefined; if (this.destroyed || this.isWindowResizing) return; if (attempt >= REVALIDATE_MAX_ATTEMPTS || !this.renderingEngineService.hasStaleCanvasResolution()) { return; } this.healViewportCameras(); this.revalidateTimeoutId = setTimeout(() => this.revalidateCanvasResolution(attempt + 1), REVALIDATE_RETRY_DELAY_MS); } handleViewportMouseMove(event, viewportId) { this.revalidateOnPointerActivity(); this.interaction.handleViewportMouseMove(event, viewportId); } /** Mouse events arrive even when the window is unfocused, so no focus or resize event * can be relied on to precede them. Check every move, heal once per movement burst. */ revalidateOnPointerActivity() { if (this.revalidateTimeoutId !== undefined || this.isWindowResizing) return; this.debouncedPointerHeal(); } onContextMenu(event) { // Suppress the browser's native context menu; our PrimeNG `ctxMenu` is // opened programmatically from `handleMouseUp` on right-clicks. event.preventDefault(); if (event.ctrlKey) { event.stopImmediatePropagation(); } } handleMouseUp(event) { const { shouldOpenContextMenu } = this.interaction.handleMouseUp(); this.cprService.releaseControlPoint(); if (shouldOpenContextMenu) { this.ctxMenu()?.show(event); } } /** A drag released outside the viewport never reaches `handleMouseUp`. */ handleWindowMouseUp() { this.interaction.handleMouseUp(); this.cprService.releaseControlPoint(); } toggleViewportContextMenu(event) { this.annotationMenuItems.set(this.annotationMenuItemService.menuItemsForViewport()); this.ctxMenu()?.toggle(event); } viewportAxis(viewportId) { return this.viewportStore.viewportAxisMapping[viewportId]; } viewportColors = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.ALTERNATEBOTTOMLEFT]: { h: 'var(--p-app-viewport-axis-coronal)', v: 'var(--p-app-viewport-axis-axial)' }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.ALTERNATETOPLEFTMAIN]: { h: 'var(--p-app-viewport-axis-sagittal)', v: 'var(--p-app-viewport-axis-coronal)' }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.BOTTOMLEFTMAIN]: { h: 'var(--p-app-viewport-axis-coronal)', v: 'var(--p-app-viewport-axis-axial)' }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.MIDDLEMAIN]: { h: 'var(--p-app-viewport-axis-axial)', v: 'var(--p-app-viewport-axis-sagittal)' }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.RIGHTMAIN]: { h: 'var(--p-app-viewport-axis-axial)', v: 'var(--p-app-viewport-axis-sagittal)' }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.ViewportAxisState.TOPLEFTMAIN]: { h: 'var(--p-app-viewport-axis-sagittal)', v: 'var(--p-app-viewport-axis-coronal)' } }; compactCrosshair(viewportId) { return this.isViewportMaximized(viewportId) || this.cprActive() && viewportId === _viewport_ids__WEBPACK_IMPORTED_MODULE_43__.VIEWPORT_IDS.REFORMAT; } viewportAxisColors(viewportId) { if (this.compactCrosshair(viewportId)) { return { h: MAXIMIZED_CROSSHAIR_COLOR, v: MAXIMIZED_CROSSHAIR_COLOR }; } return this.viewportColors[viewportId]; } viewportCrosshairRotation(viewportId) { return this.viewportStore.viewportCrosshairRotations[viewportId]; } viewportAngulation(viewportId) { return this.viewportStore.viewportAngulations[viewportId]; } viewportCameraState(viewportId) { return this.viewportStore.viewportCameras[viewportId]; } moveSCurveGraphToSidebar() { this.uiFacade.attachSCurveGraph(); this.uiFacade.openSidebarSection(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.SidebarSection.SCURVE); if (this.sCurveMaximized()) { this.toggleMaximizeViewport.emit(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_19__.LayoutType.DEFAULT); } } ngOnDestroy() { this.destroyed = true; this.inFlightPhaseLoads.clear(); // Clean up interval if component is destroyed during resize if (this.resizeIntervalId !== undefined) { clearInterval(this.resizeIntervalId); this.resizeIntervalId = undefined; } // Clean up resize timeout if (this.resizeTimeoutId !== undefined) { clearTimeout(this.resizeTimeoutId); this.resizeTimeoutId = undefined; } if (this.revalidateTimeoutId !== undefined) { clearTimeout(this.revalidateTimeoutId); this.revalidateTimeoutId = undefined; } this.seriesCacheProgressSubscription?.unsubscribe(); this.seriesCacheProgressSubscription = undefined; // Cornerstone doesn't count volumes toward its own cache size/eviction, so nothing frees // this memory unless released explicitly. RenderingEngineService's own teardown also // purges Cornerstone's cache as a side effect, but that's a separate service on a sibling // injector scope - releasing our own volumes directly here doesn't depend on that. for (const volumeIds of this.phaseVolumeIds.values()) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); } this.phaseVolumeIds.clear(); // Safety net: releases anything discardStaleVolume deferred for an in-progress reset to // pick up, in case the component is destroyed before that reset's own cleanup runs. for (const volumeIds of this.pendingStaleVolumeDiscards) { (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.decacheVolumeIds)(volumeIds); } this.pendingStaleVolumeDiscards.length = 0; } openContextMenuSubscriber() { const subscriber = this.interaction.openContextMenu$.subscribe(key => { const [viewportId, keySuffix] = key.split(':'); if (keySuffix === 'angulationMenu' && viewportId) { this.annotationMenuItems.set(this.annotationMenuItemService.menuItemsForAngulationMenu(viewportId)); return; } if (key === 'viewport') { this.annotationMenuItems.set(this.annotationMenuItemService.menuItemsForViewport()); return; } const [annotationId, pointIndexString] = key.split(':'); if (!annotationId) return; const pointIndex = pointIndexString === undefined ? undefined : Number.parseInt(pointIndexString); const annotation = this.annotationFacade.getAnnotationById(annotationId); if (annotation) { this.annotationMenuItems.set(this.annotationMenuItemService.menuItemsForAnnotation(annotation, pointIndex)); } }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.DestroyRef).onDestroy(() => { subscriber.unsubscribe(); }); } static ɵfac = function VolumeViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VolumeViewerComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵdefineComponent"]({ type: VolumeViewerComponent, selectors: [["lib-volume-viewer"]], viewQuery: function VolumeViewerComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵviewQuerySignal"](ctx.ctxMenu, _c0, 5)(ctx.alignMenu, _c1, 5)(ctx.cprWorkspace, _cpr_cpr_workspace_component__WEBPACK_IMPORTED_MODULE_36__.CprWorkspaceComponent, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵqueryAdvance"](3); } }, hostBindings: function VolumeViewerComponent_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵlistener"]("keydown.escape", function VolumeViewerComponent_keydown_escape_HostBindingHandler($event) { return ctx.handleKeyDown($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("keydown.enter", function VolumeViewerComponent_keydown_enter_HostBindingHandler($event) { return ctx.handleEnterKey($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("keydown.delete", function VolumeViewerComponent_keydown_delete_HostBindingHandler($event) { return ctx.handleDeleteKey($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("keydown.backspace", function VolumeViewerComponent_keydown_backspace_HostBindingHandler($event) { return ctx.handleDeleteKey($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"])("resize", function VolumeViewerComponent_resize_HostBindingHandler() { return ctx.onWindowResize(); }, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵresolveWindow"]); } }, inputs: { seriesUid: [1, "seriesUid"], studyUid: [1, "studyUid"], storeUid: [1, "storeUid"], otSeriesUid: [1, "otSeriesUid"], workSessionUid: [1, "workSessionUid"], selectedPhaseIds: [1, "selectedPhaseIds"], layoutConfig: [1, "layoutConfig"], viewportLayout: [1, "viewportLayout"], focusedMPRViewport: [1, "focusedMPRViewport"], selectedMPRViewport: [1, "selectedMPRViewport"], isInitialViewportLayout: [1, "isInitialViewportLayout"], lastSelectedMPRViewport: [1, "lastSelectedMPRViewport"], cameraSliderTemplate: [1, "cameraSliderTemplate"] }, outputs: { toggleMaximizeViewport: "toggleMaximizeViewport", focusedMPRViewportChange: "focusedMPRViewportChange", selectedMPRViewportChange: "selectedMPRViewportChange", escPressed: "escPressed" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵProvidersFeature"]([_annotation_actors_annotation_actors_service__WEBPACK_IMPORTED_MODULE_34__.AnnotationActorsService, _viewport_interaction_viewport_interaction_service__WEBPACK_IMPORTED_MODULE_44__.ViewportInteractionService, _ct_popover_service__WEBPACK_IMPORTED_MODULE_38__.CtPopoverService, _volume_rendering_popover_service__WEBPACK_IMPORTED_MODULE_46__.VolumeRenderingPopoverService])], decls: 15, vars: 5, consts: [["volumeRenderTrigger", ""], ["volumeRenderMaximized", ""], ["ctPopoverSettings", ""], ["viewportPopoverSettings", ""], ["annotationCards", ""], ["viewportBase", ""], ["wrapper", ""], ["ctxMenu", ""], ["item", ""], ["alignMenu", ""], ["viewportAxial", ""], ["viewportSagittal", ""], ["viewportCoronal", ""], ["viewportReformat", ""], ["sCurveGraph", ""], ["cprWorkspace", ""], ["moreActionsMenu", ""], [1, "p-4", "text-center", "text-(--p-app-status-danger)"], ["data-viewer-bounds", "", 1, "h-full", "w-full", "bg-(--p-app-viewport-background)", 3, "cursor"], ["data-test-id", "volume-viewer-p-menu-hidden", 3, "pt"], ["data-viewer-bounds", "", 1, "h-full", "w-full", "bg-(--p-app-viewport-background)", 3, "mouseup", "mousemove", "blur"], [1, "relative", "h-full", "w-full", 3, "contextmenu"], [1, "pointer-events-auto", "absolute", "top-6", "left-6", "z-30"], [3, "viewportLayout", "focusedMPRViewport", "selectedMPRViewport", "isInitialViewportState", "lastSelectedMPRViewport", "isBlur", "loadingProgress", "showSCurveGraph"], [3, "onShow", "onHide", "appendTo", "model", "pt"], [3, "model"], [1, "absolute", "bottom-12", "left-1/2", "z-20", "-translate-x-1/2"], ["data-test-id", "volume-viewer-p-select-volume-selector", "optionLabel", "label", "optionValue", "value", "appendTo", "body", 3, "ngModelChange", "options", "ngModel", "disabled", "ariaLabel"], [3, "resizeStart", "resizeEnd", "loaderContextMenu", "viewportLayout", "focusedMPRViewport", "selectedMPRViewport", "isInitialViewportState", "lastSelectedMPRViewport", "isBlur", "loadingProgress", "showSCurveGraph"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], ["display", "inline-block", 1, "absolute", "bottom-0", "left-0", "z-10", "flex", "max-w-full", "flex-col", "gap-2", "py-2", "pr-2", "pl-6"], [1, "flex", "h-8", "items-center", "gap-1"], ["tooltipPosition", "top", "iconType", "prime", 3, "click", "tooltip", "ariaLabel", "icon"], ["icon", "window-minimize", "iconType", "prime", "tooltipPosition", "top", 3, "click", "tooltip", "ariaLabel"], [1, "flex", "h-full", "w-full", "items-center", "justify-center"], [1, "aspect-square", "h-full", "max-h-full", "max-w-full"], [3, "showDetachButton", "isMaximized"], [3, "resizeStart", "resizeEnd", "axialTemplate", "cameraSliderTemplate", "coronalTemplate", "reformatTemplate", "sagittalTemplate", "isBlur", "isInitialViewportState", "lastSelectedMPRViewport", "selectedMPRViewport"], [3, "item"], ["data-test-id", "volume-viewer-lib-settings-popover-orientation", 3, "visibilityChange", "closed", "showButton", "draggable", "dragBoundary", "externalOpen", "formFieldConfig", "title", "dragHandleAriaLabel"], [3, "visibilityChange", "closed", "showButton", "externalOpen", "formFieldConfig", "title"], ["tooltipPosition", "top", "iconType", "prime", "icon", "sliders-h", "iconClass", "text-lg", 3, "tooltip", "ariaLabel"], ["tooltipPosition", "top", "iconType", "prime", "icon", "sliders-h", "iconClass", "text-lg", 3, "click", "tooltip", "ariaLabel"], [3, "formFieldConfig", "buttonTooltip", "buttonAriaLabel", "title"], [3, "visibilityChange", "formFieldConfig", "buttonTooltip", "buttonAriaLabel", "title"], [3, "formFieldConfig", "draggable", "dragBoundary", "buttonTooltip", "buttonAriaLabel", "title", "dragHandleAriaLabel"], [3, "visibilityChange", "formFieldConfig", "draggable", "dragBoundary", "buttonTooltip", "buttonAriaLabel", "title", "dragHandleAriaLabel"], ["icon", "ellipsis-v", "tooltipPosition", "top", 3, "click", "tooltip", "ariaLabel"], [3, "pt", "multiple", "value"], [3, "valueChange", "pt", "multiple", "value"], ["selected", "", 3, "show", "hide", "goTo", "updateName", "annotation", "actions", "menuTrigger", "pt"], [3, "viewportReady", "viewportDestroyed", "perspectiveChange", "mouseDown", "mouseMove", "wheelScrolled", "gestureStarted", "gestureChanged", "gestureEnded", "contextMenu", "toggleMaximizeViewport", "focusedMPRViewportChange", "state", "darkMode", "annotationCardsTemplate", "settingsPopoverTemplate", "viewportSettingsPopoverTemplate", "includeViewportSwap", "maximized", "includeViewportMenu", "angulation", "createMode", "cursor", "isPosterior", "swapLabel", "minimizeLabel", "maximizeLabel"], [3, "viewportId", "viewportAxis", "cameraDetails", "crosshairColors", "crosshairRotation", "compact"], [1, "pointer-events-auto", "absolute", "right-4", "bottom-4", "z-50"], [1, "pointer-events-none", "absolute", "inset-0", "z-40", "flex", "items-center", "justify-center", "bg-(--p-app-viewport-background)/60"], [1, "pointer-events-auto", "absolute", "right-4", "bottom-4", "z-50", 3, "mousedown", "wheel"], [1, "border-surface-500", "h-8", "w-8", "animate-spin", "rounded-full", "border-4", "border-t-(--p-app-viewport-label)"]], template: function VolumeViewerComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditionalCreate"](0, VolumeViewerComponent_Conditional_0_Template, 3, 1, "div", 17)(1, VolumeViewerComponent_Conditional_1_Template, 12, 9, "section", 18); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplate"](2, VolumeViewerComponent_ng_template_2_Template, 1, 1, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(4, VolumeViewerComponent_ng_template_4_Template, 1, 1, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(6, VolumeViewerComponent_ng_template_6_Template, 1, 1, "ng-template", null, 2, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(8, VolumeViewerComponent_ng_template_8_Template, 3, 6, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(10, VolumeViewerComponent_ng_template_10_Template, 4, 2, "ng-template", null, 4, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"])(12, VolumeViewerComponent_ng_template_12_Template, 9, 31, "ng-template", null, 5, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵelement"](14, "p-menu", 19); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵconditional"](ctx.viewerOrchestrator.status() === "error" ? 0 : 1); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵadvance"](14); _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction1"](3, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_48__["ɵɵpureFunction0"](2, _c2))); } }, dependencies: [primeng_accordion__WEBPACK_IMPORTED_MODULE_11__.Accordion, _annotation_card_annotation_card_component__WEBPACK_IMPORTED_MODULE_23__.AnnotationCardComponent, _annotation_menu_components_annotation_menu_component__WEBPACK_IMPORTED_MODULE_26__.AnnotationMenuComponent, _annotation_menu_components_annotation_menu_item_component__WEBPACK_IMPORTED_MODULE_25__.AnnotationMenuItemComponent, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_13__.ContextMenuModule, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_13__.ContextMenu, _cpr_cpr_workspace_component__WEBPACK_IMPORTED_MODULE_36__.CprWorkspaceComponent, _endo_dev_panel_endo_dev_panel_component__WEBPACK_IMPORTED_MODULE_39__.EndoDevelopmentPanelComponent, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_6__.NgModel, primeng_menu__WEBPACK_IMPORTED_MODULE_15__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_15__.Menu, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _render_quality_dev_panel_render_quality_dev_panel_component__WEBPACK_IMPORTED_MODULE_41__.RenderQualityDevelopmentPanelComponent, _s_curve_graph_s_curve_graph_component__WEBPACK_IMPORTED_MODULE_32__.SCurveGraphComponent, primeng_select__WEBPACK_IMPORTED_MODULE_16__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_16__.Select, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.SettingsPopoverComponent, _vascular_dev_panel_vascular_dev_panel_component__WEBPACK_IMPORTED_MODULE_42__.VascularDevelopmentPanelComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.ViewportButtonComponent, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.ViewportLayoutManagerComponent, _viewport_overlay_viewport_overlay_component__WEBPACK_IMPORTED_MODULE_45__.ViewportOverlay, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.VolumeViewportComponent, _angular_common__WEBPACK_IMPORTED_MODULE_1__.JsonPipe, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_10__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 48333 /*!********************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/vtk-poly-line-source.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ extend: () => (/* binding */ extend), /* harmony export */ newInstance: () => (/* binding */ newInstance) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/PolyData */ 95765); /* harmony import */ var _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/macros */ 64946); /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/no-explicit-any */ function vtkPolyLineSource(publicAPI, model) { // Set our className model.classHierarchy.push('vtkPolyLineSource'); publicAPI.requestData = (inData, outData) => { const dataset = outData[0]; // Check input const pointDataType = dataset ? dataset.getPoints().getDataType() : model.pointType; const pd = dataset?.initialize() ?? _kitware_vtk_js_Common_DataModel_PolyData__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); const modelPoints = model.points; const pointCount = modelPoints.length; const points = _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__["default"].newTypedArray(pointDataType, pointCount * 3); pd.getPoints().setData(points, 3); const lines = new Uint32Array(pointCount + 1); pd.getLines().setData(lines, 1); lines[0] = pointCount; for (const [index, point] of modelPoints.entries()) { points[index * 3] = point[0]; points[index * 3 + 1] = point[1]; points[index * 3 + 2] = point[2]; lines[index + 1] = index; } outData[0] = pd; }; } const DEFAULT_VALUES = { points: [], pointType: 'Float64Array' }; function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__["default"].obj(publicAPI, model); _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__["default"].setGet(publicAPI, model, ['points']); _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__["default"].algo(publicAPI, model, 0, 1); vtkPolyLineSource(publicAPI, model); } const newInstance = _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(extend, 'vykPolyLineSource'); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ extend, newInstance }); /***/ }, /***/ 99360 /*!*************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/window-details/window-details.service.ts ***! \*************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WindowDetailsService: () => (/* binding */ WindowDetailsService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 87510); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 57168); /** * A centralized service that listens for window resizes and exposes * Signals representing various properties. */ class WindowDetailsService { _devicePixelRatio = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(globalThis.devicePixelRatio, ...(ngDevMode ? [{ debugName: "_devicePixelRatio" }] : [])); devicePixelRatio = this._devicePixelRatio.asReadonly(); _screenHeight = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(globalThis.innerHeight, ...(ngDevMode ? [{ debugName: "_screenHeight" }] : [])); screenHeight = this._screenHeight.asReadonly(); _screenWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(globalThis.innerWidth, ...(ngDevMode ? [{ debugName: "_screenWidth" }] : [])); screenWidth = this._screenWidth.asReadonly(); constructor() { const windowResize = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.fromEvent)(globalThis, 'resize').pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_3__.debounceTime)(100), (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_1__.takeUntilDestroyed)()).subscribe(() => { this._screenWidth.set(window.innerWidth); this._screenHeight.set(window.innerHeight); this._devicePixelRatio.set(window.devicePixelRatio); }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { windowResize.unsubscribe(); }); } static ɵfac = function WindowDetailsService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WindowDetailsService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: WindowDetailsService, factory: WindowDetailsService.ɵfac }); } /***/ }, /***/ 26914 /*!*******************************************************!*\ !*** ./libs/feature/src/lib/window/window.service.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WindowService: () => (/* binding */ WindowService) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); class WindowService { document = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT); isFullscreen = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__.signal)(Boolean(this.document.fullscreenElement), ...(ngDevMode ? [{ debugName: "isFullscreen" }] : [])); constructor() { const onFullscreenChange = () => { this.isFullscreen.set(Boolean(this.document.fullscreenElement)); }; this.document.addEventListener('fullscreenchange', onFullscreenChange); (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { this.document.removeEventListener('fullscreenchange', onFullscreenChange); }); } toggleFullscreen() { if (this.document.fullscreenElement) { this.document.exitFullscreen?.(); return; } this.document.documentElement.requestFullscreen?.(); } static ɵfac = function WindowService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WindowService)(); }; static ɵprov = /*@__PURE__*/_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: WindowService, factory: WindowService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 76774 /*!*****************************************************************************!*\ !*** ./libs/feature/src/lib/work-session-nav/work-session-nav.component.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionNavComponent: () => (/* binding */ WorkSessionNavComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/router */ 38709); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 90100); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 84356); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 69042); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 84917); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxjs */ 9276); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! rxjs */ 45541); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_skeleton__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/skeleton */ 65528); /* harmony import */ var primeng_tabs__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! primeng/tabs */ 70021); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _pipes_modality_label_pipe__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../pipes/modality-label.pipe */ 18194); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ root: "overflow-x-hidden" }); const _c1 = () => ({ transitionDuration: 0 }); const _c2 = () => ({ background: "transparent", borderWidth: 0 }); const _c3 = () => ({ background: "{amber.300}", color: "{surface.800}" }); const _c4 = a0 => ({ color: "{surface.200}", hoverColor: "{surface.200}", active: a0 }); const _c5 = a0 => ({ dark: a0 }); const _c6 = a0 => ({ padding: "0 0.5rem 0 1rem", fontWeight: 500, colorScheme: a0 }); const _c7 = (a0, a1, a2) => ({ root: a0, tablist: a1, tab: a2 }); const _c8 = () => ({ content: "overflow-x-auto no-scrollbar scroll-smooth flex-nowrap py-2", activeBar: "hidden" }); const _c9 = () => ({ root: "min-w-0 max-w-60 basis-60 border-none rounded-[var(--p-button-border-radius)]" }); const _c10 = (a0, a1, a2, a3) => ["/volume-viewer", a0, a1, a2, a3]; const _c11 = () => []; const _c12 = () => ({ background: "{app.surface.tab}" }); const _c13 = a0 => ({ root: a0 }); const _forTrack0 = ($index, $item) => $item.uid; function WorkSessionNavComponent_Conditional_1_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementContainer"](0); } } function WorkSessionNavComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](0, WorkSessionNavComponent_Conditional_1_ng_container_0_Template, 1, 0, "ng-container", 3); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); const skeleton_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreference"](6); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("ngTemplateOutlet", skeleton_r1); } } function WorkSessionNavComponent_Conditional_2_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementContainer"](0); } } function WorkSessionNavComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](0, WorkSessionNavComponent_Conditional_2_ng_container_0_Template, 1, 0, "ng-container", 3); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); const tabs_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵreference"](4); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("ngTemplateOutlet", tabs_r2); } } function WorkSessionNavComponent_ng_template_3_For_4_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "p-tab", 7)(1, "div", 8); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](2, "lib-work-session-tab", 9); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](3, "button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipe"](4, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵlistener"]("click", function WorkSessionNavComponent_ng_template_3_For_4_Template_button_click_3_listener($event) { const workSession_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrestoreView"](_r3).$implicit; const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresetView"](ctx_r4.closeTab(workSession_r4, $event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](5, "lib-icon", 11); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"]()()(); } if (rf & 2) { const workSession_r4 = ctx.$implicit; const ɵ$index_21_r6 = ctx.$index; const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](13, _c9))("routerLink", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction4"](14, _c10, workSession_r4.storeUid, workSession_r4.studyUid, workSession_r4.seriesUid, workSession_r4.uid))("value", workSession_r4.uid)("libScrollToActive", workSession_r4.uid === ctx_r4.displayedActiveUid()); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵattribute"]("data-test-id", "work-session-nav-p-tab-" + ɵ$index_21_r6); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("details", workSession_r4)("mutedTextPt", ctx_r4.cn(workSession_r4.uid === ctx_r4.displayedActiveUid() && "text-surface-600")); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵclassMap"](ctx_r4.cn(workSession_r4.uid === ctx_r4.displayedActiveUid() ? "text-surface-600 hover:bg-primary-200" : "text-muted-color hover:bg-surface-700 hover:text-surface-200")); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵattribute"]("data-test-id", "work-session-nav-button-close-" + ɵ$index_21_r6)("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpipeBind1"](4, 11, "workSessionNav.closeTab")); } } function WorkSessionNavComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "p-tabs", 4)(1, "p-tablist", 5)(2, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵrepeaterCreate"](3, WorkSessionNavComponent_ng_template_3_For_4_Template, 6, 19, "p-tab", 7, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"]()()(); } if (rf & 2) { const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("value", ctx_r4.displayedActiveUid())("showNavigators", false)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](5, _c0))("dt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction3"](15, _c7, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](6, _c1), _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](7, _c2), _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction1"](13, _c6, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction1"](11, _c5, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction1"](9, _c4, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](8, _c3)))))); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](19, _c8)); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵrepeater"](ctx_r4.formattedSessions()); } } function WorkSessionNavComponent_ng_template_5_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelement"](0, "p-skeleton", 13); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction1"](2, _c13, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](1, _c12))); } } function WorkSessionNavComponent_ng_template_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵrepeaterCreate"](1, WorkSessionNavComponent_ng_template_5_For_2_Template, 1, 4, "p-skeleton", 13, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵrepeaterTrackByIndex"]); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵrepeater"](_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵpureFunction0"](0, _c11).constructor(ctx_r4.sessionCount())); } } class WorkSessionNavComponent { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_23__.getLogger)(WorkSessionNavComponent.name); workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.WorkSessionDatabaseService); dicomDatabase = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.DicomDatabaseService); recentWorkSessions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_20__.RecentWorkSessionsService); router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_6__.Router); modalityLabelPipe = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_pipes_modality_label_pipe__WEBPACK_IMPORTED_MODULE_24__.ModalityLabelPipe); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_17__.TranslateService); translationChanges$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.merge)(this.translate.onLangChange, this.translate.onTranslationChange).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_14__.startWith)(undefined)); activeWorkSessionUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.input)(undefined, ...(ngDevMode ? [{ debugName: "activeWorkSessionUid" }] : [])); sessionCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => this.recentWorkSessions.sessions().length, ...(ngDevMode ? [{ debugName: "sessionCount" }] : [])); isInitialLoading = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.signal)(true, ...(ngDevMode ? [{ debugName: "isInitialLoading" }] : [])); formattedSessions = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_5__.toObservable)(this.recentWorkSessions.sessions).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_15__.switchMap)(references => references.length === 0 ? (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.of)([]) : (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.combineLatest)(references.map(reference => this.sessionDetails$(reference)))), (0,rxjs__WEBPACK_IMPORTED_MODULE_16__.tap)(() => this.isInitialLoading.set(false)), (0,rxjs__WEBPACK_IMPORTED_MODULE_13__.map)(tabs => tabs.filter(details => !!details))), { initialValue: [] }); /** * The uid whose tab is shown as active. Usually the routed session, but while a * freshly opened session's tab has not rendered yet (its local document or series * metadata is still loading), the previously active tab keeps its active state so * the tab strip never shows a gap with no active tab. */ displayedActiveUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.linkedSignal)({ ...(ngDevMode ? { debugName: "displayedActiveUid" } : {}), computation: ({ active, sessions }, previous) => { if (!active) return ''; if (sessions.some(session => session.uid === active)) return active; // Only hold the previous tab while it still exists. const held = previous?.value; return held && sessions.some(session => session.uid === held) ? held : ''; }, source: () => ({ active: this.activeWorkSessionUid(), sessions: this.formattedSessions() }) }); seriesMetadataCache = new Map(); seriesMetadata(reference) { const key = `${reference.storeUid}/${reference.studyUid}/${reference.seriesUid}`; let metadata = this.seriesMetadataCache.get(key); if (!metadata) { metadata = this.dicomDatabase.getSeriesCommonMetadata(reference.studyUid, reference.seriesUid, reference.storeUid).catch(error => { this.seriesMetadataCache.delete(key); this.log.error('Failed to load series metadata for a recent work session', error); }); this.seriesMetadataCache.set(key, metadata); } return metadata; } sessionDetails$(reference) { return (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.combineLatest)([this.workSessionDb.get$(reference.workSessionUid), (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.from)(this.seriesMetadata(reference)), this.translationChanges$]).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_13__.map)(([session, metadata]) => { if (!session) return; const dateObject = new Date(session.createdAt); const missing = key => this.translate.instant(`workSessionNav.metadata.${key}`); return { ...session, date: dateObject.toLocaleDateString(), description: metadata?.studyDescription ?? missing('unknownStudy'), modality: metadata?.modality ? this.modalityLabelPipe.transform(metadata.modality) : missing('notAvailable'), modalityTag: metadata?.modality ?? '??', patient: { birthdate: metadata?.patientBirthDate ?? missing('unknown'), gender: metadata?.patientSex ?? 'U', mrn: metadata?.patientID ?? missing('notAvailable'), name: metadata?.patientName ?? missing('anonymous') }, time: dateObject.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) }; }), (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.catchError)(error => { this.log.error('Failed to load a recent work session', error); return (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.of)(undefined); })); } closeTab(session, event) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { event.stopPropagation(); event.preventDefault(); if (session.uid === _this.activeWorkSessionUid()) { const navigated = yield _this.router.navigate(['/library']); if (!navigated) return; } _this.recentWorkSessions.remove(session.uid); })(); } cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_22__.cn; static ɵfac = function WorkSessionNavComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionNavComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵdefineComponent"]({ type: WorkSessionNavComponent, selectors: [["lib-work-session-nav"]], inputs: { activeWorkSessionUid: [1, "activeWorkSessionUid"] }, decls: 7, vars: 1, consts: [["tabs", ""], ["skeleton", ""], [1, "flex", "w-full", "min-w-0"], [4, "ngTemplateOutlet"], [3, "value", "showNavigators", "pt", "dt"], [3, "pt"], [1, "flex", "gap-3"], [3, "pt", "routerLink", "value", "libScrollToActive"], [1, "flex", "w-full", "min-w-0", "items-center", "gap-2"], [1, "min-w-0", "flex-1", 3, "details", "mutedTextPt"], ["type", "button", 1, "flex", "size-6", "shrink-0", "cursor-pointer", "items-center", "justify-center", "rounded-md", "transition-colors", 3, "click"], ["icon", "times", 1, "text-xs"], [1, "flex", "gap-3", "py-2"], ["width", "15rem", "height", "2.8rem", "borderRadius", "var(--p-button-border-radius)", 3, "dt"]], template: function WorkSessionNavComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementStart"](0, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditionalCreate"](1, WorkSessionNavComponent_Conditional_1_Template, 1, 1, "ng-container")(2, WorkSessionNavComponent_Conditional_2_Template, 1, 1, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplate"](3, WorkSessionNavComponent_ng_template_3_Template, 5, 20, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"])(5, WorkSessionNavComponent_ng_template_5_Template, 3, 1, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_25__["ɵɵconditional"](ctx.isInitialLoading() ? 1 : 2); } }, dependencies: [_angular_router__WEBPACK_IMPORTED_MODULE_7__.RouterLink, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.IconComponent, primeng_tabs__WEBPACK_IMPORTED_MODULE_19__.Tabs, primeng_tabs__WEBPACK_IMPORTED_MODULE_19__.TabList, primeng_tabs__WEBPACK_IMPORTED_MODULE_19__.Tab, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.WorkSessionTabComponent, primeng_skeleton__WEBPACK_IMPORTED_MODULE_18__.Skeleton, _angular_common__WEBPACK_IMPORTED_MODULE_1__.NgTemplateOutlet, _tomoverse_ui__WEBPACK_IMPORTED_MODULE_21__.ScrollToActiveDirective, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_17__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 2643 /*!**************************************************************************************************************!*\ !*** ./libs/feature/src/lib/work-session/create-work-session-dialog/create-work-session-dialog.component.ts ***! \**************************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CreateWorkSessionDialogComponent: () => (/* binding */ CreateWorkSessionDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_checkbox__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/checkbox */ 10026); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_floatlabel__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/floatlabel */ 95717); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 14975); function CreateWorkSessionDialogComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](2, "div"); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate"](ctx_r0.config.data == null ? null : ctx_r0.config.data.warning); } } function CreateWorkSessionDialogComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "small", 4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", (ctx_r0.config.data == null ? null : ctx_r0.config.data.duplicateNameError) || "Analysis name already exists.", " "); } } function CreateWorkSessionDialogComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "p-button", 10); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("onClick", function CreateWorkSessionDialogComponent_Conditional_8_Template_p_button_onClick_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵrestoreView"](_r2); const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵresetView"](ctx_r0.discard()); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("label", ctx_r0.config.data == null ? null : ctx_r0.config.data.discardLabel); } } class CreateWorkSessionDialogComponent { ref = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DynamicDialogRef); config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_4__.DynamicDialogConfig); form = new _angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormGroup({ name: new _angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormControl('', { nonNullable: true, validators: [_angular_forms__WEBPACK_IMPORTED_MODULE_1__.Validators.required, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.Validators.pattern(String.raw`.*\S.*`)] }) }); ngOnInit() { const existingNames = new Set(this.config.data?.existingNames); this.form.controls.name.addValidators(this.uniqueNameValidator(existingNames)); this.form.patchValue({ name: this.config.data?.name }); } submit() { if (!this.form.valid) return; this.ref.close({ name: this.form.controls.name.value.trim() }); } discard() { this.ref.close({ discard: true }); } close() { this.ref.close(); } uniqueNameValidator(existingNames) { return control => { const value = control.value.trim(); // eslint-disable-next-line unicorn/no-null -- Angular requires null for "no error" if (!value) return null; // eslint-disable-next-line unicorn/no-null return existingNames.has(value) ? { nameTaken: true } : null; }; } static ɵfac = function CreateWorkSessionDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CreateWorkSessionDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineComponent"]({ type: CreateWorkSessionDialogComponent, selectors: [["lib-create-work-session-dialog"]], decls: 11, vars: 8, consts: [[1, "flex", "flex-col", "gap-5", "pt-2", 3, "ngSubmit", "formGroup"], ["variant", "on"], ["data-test-id", "create-work-session-dialog-input-name", "pInputText", "", "id", "work-session-name", "formControlName", "name", "fluid", "", "autofocus", ""], ["for", "work-session-name"], [1, "text-(--p-app-status-danger)"], [1, "flex", "justify-end", "gap-2"], ["data-test-id", "create-work-session-dialog-p-button-discard", "type", "button", "outlined", "", "severity", "danger", "size", "small", 1, "mr-auto", 3, "label"], ["data-test-id", "create-work-session-dialog-p-button-cancel", "type", "button", "outlined", "", "severity", "secondary", "size", "small", 3, "onClick", "label"], ["data-test-id", "create-work-session-dialog-p-button-submit", "type", "submit", "severity", "contrast", "size", "small", 3, "label", "disabled"], [1, "text-primary-500"], ["data-test-id", "create-work-session-dialog-p-button-discard", "type", "button", "outlined", "", "severity", "danger", "size", "small", 1, "mr-auto", 3, "onClick", "label"]], template: function CreateWorkSessionDialogComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "form", 0); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("ngSubmit", function CreateWorkSessionDialogComponent_Template_form_ngSubmit_0_listener() { return ctx.submit(); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](1, CreateWorkSessionDialogComponent_Conditional_1_Template, 3, 1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](2, "p-floatlabel", 1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](3, "input", 2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](4, "label", 3); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](6, CreateWorkSessionDialogComponent_Conditional_6_Template, 2, 1, "small", 4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](7, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](8, CreateWorkSessionDialogComponent_Conditional_8_Template, 1, 1, "p-button", 6); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](9, "p-button", 7); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("onClick", function CreateWorkSessionDialogComponent_Template_p_button_onClick_9_listener() { return ctx.close(); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelement"](10, "p-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("formGroup", ctx.form); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"]((ctx.config.data == null ? null : ctx.config.data.warning) ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate"]((ctx.config.data == null ? null : ctx.config.data.titleLabel) || "Analysis name"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx.form.controls.name.touched && ctx.form.controls.name.hasError("nameTaken") ? 6 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"]((ctx.config.data == null ? null : ctx.config.data.discardLabel) ? 8 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("label", (ctx.config.data == null ? null : ctx.config.data.cancelLabel) || "Cancel"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("label", (ctx.config.data == null ? null : ctx.config.data.createLabel) || "Create")("disabled", ctx.form.invalid); } }, dependencies: [primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_6__.InputText, primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_1__["ɵNgNoValidate"], _angular_forms__WEBPACK_IMPORTED_MODULE_1__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.NgControlStatusGroup, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormGroupDirective, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormControlName, primeng_floatlabel__WEBPACK_IMPORTED_MODULE_5__.FloatLabel, primeng_checkbox__WEBPACK_IMPORTED_MODULE_3__.CheckboxModule], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 35009 /*!**************************************************************************!*\ !*** ./libs/feature/src/lib/work-session/work-session-dialog.service.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionDialogService: () => (/* binding */ WorkSessionDialogService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 56435); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _create_work_session_dialog_create_work_session_dialog_component__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./create-work-session-dialog/create-work-session-dialog.component */ 2643); class WorkSessionDialogService { dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_5__.DialogService); confirmationService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_4__.ConfirmationService); workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_6__.WorkSessionDatabaseService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); confirmCloseOpenWorkSession(name) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const closeLabel = _this.translate.instant('workSession.alreadyOpen.accept'); const cancelLabel = _this.translate.instant('common.cancel'); return new Promise(resolve => { _this.confirmationService.confirm({ accept: () => resolve(true), acceptButtonProps: { label: closeLabel }, acceptLabel: closeLabel, defaultFocus: 'accept', header: _this.translate.instant('workSession.alreadyOpen.header'), icon: 'exclamation-triangle', message: _this.translate.instant('workSession.alreadyOpen.message', { name }), // Escape and the close icon reject too, so the promise always settles. reject: () => resolve(false), rejectButtonProps: { label: cancelLabel, outlined: true, severity: 'secondary' }, rejectLabel: cancelLabel }); }); })(); } unsavedWorkSessionDialog() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (dialogOverrides = {}) { return _this2.workSessionNameDialog({ createLabel: _this2.translate.instant('common.save'), discardLabel: _this2.translate.instant('workSession.unsaved.discard'), warning: _this2.translate.instant('workSession.unsaved.message'), ...dialogOverrides }, _this2.translate.instant('workSession.unsaved.header')); }).apply(this, arguments); } workSessionNameDialog() { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (dialogOverrides = {}, header) { const workSessions = yield _this3.workSessionDb.find(); const existingNames = workSessions.map(({ name }) => ({ name })); const newName = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.generateUniqueName)(existingNames, 'name', _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.ANALYSIS_BASE_NAME); const dialogReference = _this3.dialogService.open(_create_work_session_dialog_create_work_session_dialog_component__WEBPACK_IMPORTED_MODULE_8__.CreateWorkSessionDialogComponent, { closable: true, data: { cancelLabel: _this3.translate.instant('common.cancel'), createLabel: _this3.translate.instant('workSessionNav.createSession.accept'), duplicateNameError: _this3.translate.instant('workSession.import.nameExists'), existingNames: existingNames.map(({ name }) => name), name: newName, ...dialogOverrides }, header: header ?? _this3.translate.instant('workSessionNav.createSession.header'), width: '30rem' }); if (!dialogReference) return; return yield (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.firstValueFrom)(dialogReference.onClose); }).apply(this, arguments); } static ɵfac = function WorkSessionDialogService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionDialogService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: WorkSessionDialogService, factory: WorkSessionDialogService.ɵfac }); } /***/ }, /***/ 50784 /*!**************************************************************************!*\ !*** ./libs/feature/src/lib/work-session/work-session-import.service.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionImportService: () => (/* binding */ WorkSessionImportService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxdb */ 64062); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @tomoverse/utils */ 49585); class WorkSessionImportService { workSessionDb = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_7__.WorkSessionDatabaseService); messageService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_4__.MessageService); translate = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); document = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT); router = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_2__.Router); import() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const importResult = yield _this.readAndValidateImportFile(); if (!importResult) return; const { _attachments, ...importedWorkSession } = importResult; const existingNames = yield _this.getExistingWorkSessionNames(importedWorkSession.studyUid, importedWorkSession.seriesUid, importedWorkSession.storeUid); yield (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this.saveImportedWorkSession({ ...importedWorkSession, name: _this.resolveUniqueName(importedWorkSession.name, existingNames) }, _attachments); })); _this.messageService.add({ severity: 'success', summary: _this.translate.instant('workSession.importSuccess') }); } catch (error) { _this.messageService.add({ detail: error.message, severity: 'error', sticky: true, summary: _this.translate.instant('workSession.importError') }); } })(); } readAndValidateImportFile() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const parsedJson = yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.importFromJsonFile)(_this2.document); if (!parsedJson) return; const { _attachments, ...workSession } = parsedJson; const normalizedWorkSession = _this2.normalizeWorkSession(workSession); const parseResult = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_6__.workSessionSchema.safeParse(normalizedWorkSession); if (!parseResult.success) { throw new Error(_this2.formatZodError(parseResult.error)); } return { ...parseResult.data, _attachments: _attachments ?? [] }; })(); } normalizeRenderSettings(renderSettings) { const existing = renderSettings && typeof renderSettings === 'object' ? renderSettings : {}; return { sCurveGraphFontSize: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE, sCurveLineWidth: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_S_CURVE_LINE_WIDTH, ...existing }; } normalizeWorkSession(workSession) { const volumes = workSession['volumes']; if (!Array.isArray(volumes)) return workSession; return { ...workSession, renderSettings: this.normalizeRenderSettings(workSession['renderSettings']), volumes: volumes.map(volume => { const { renderSettings, sCurves, ...rest } = volume; return { chambers: [], sCurveRelativeMeasurements: [], ...rest, renderSettings: this.normalizeRenderSettings(renderSettings), sCurves: Array.isArray(sCurves) ? sCurves : [] }; }) }; } formatZodError(error) { return error.issues.map(issue => { const path = issue.path.map(p => typeof p === 'number' ? `[${p}]` : p).join('.').replaceAll('.[', '['); return `- ${issue.message} -> ${path || 'root'}`; }).join('\n'); } getExistingWorkSessionNames(studyUid, seriesUid, storeUid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessions = yield _this3.workSessionDb.find({ seriesUid, storeUid, studyUid }); return new Set(workSessions.map(session => session.name.trim())); })(); } resolveUniqueName(importedName, existingNames) { const name = importedName.trim(); if (name && !existingNames.has(name)) return name; const existingItems = [...existingNames].map(existing => ({ name: existing })); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.generateUniqueName)(existingItems, 'name', name || _tomoverse_utils__WEBPACK_IMPORTED_MODULE_9__.ANALYSIS_BASE_NAME); } saveImportedWorkSession(_x) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (data, attachments = []) { data['uid'] = crypto.randomUUID(); // Must run before the first write, or the new session reaches the backend. yield _this4.workSessionDb.markDraft(data.uid); yield _this4.workSessionDb.save(data, { attachments: yield Promise.all(attachments.map(/*#__PURE__*/function () { var _ref2 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (attachment) { return { ...attachment, data: yield (0,rxdb__WEBPACK_IMPORTED_MODULE_5__.createBlobFromBase64)(attachment.data, attachment.type) }; }); return function (_x2) { return _ref2.apply(this, arguments); }; }())) }); yield _this4.router.navigate(['/volume-viewer', data.storeUid, data.studyUid, data.seriesUid, data.uid]); }).apply(this, arguments); } } /***/ }, /***/ 5497 /*!**************************************************************************!*\ !*** ./libs/feature/src/lib/work-session/work-session-switch.service.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionSwitchService: () => (/* binding */ WorkSessionSwitchService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _work_session_dialog_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./work-session-dialog.service */ 35009); const hasFormValue = value => Array.isArray(value) ? value.length > 0 : value !== undefined && value !== ''; const bundleHasWork = bundle => { if (bundle.annotations.length > 0) return true; if (bundle.chambers.length > 0) return true; if (bundle.sCurves.length > 0) return true; if (bundle.sCurveRelativeMeasurements.length > 0) return true; return bundle.protocolData.instances.some(instance => Object.values(instance.formValues ?? {}).some(value => hasFormValue(value))); }; class WorkSessionSwitchService { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_6__.getLogger)(WorkSessionSwitchService.name); workSessionDb = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.WorkSessionDatabaseService); workSessionDialog = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_7__.WorkSessionDialogService); workSessionNavService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.WorkSessionNavigationService); recentWorkSessions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.RecentWorkSessionsService); messageService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_3__.MessageService); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateService); // An analysis is open while its tab is, so this runs on arrival rather than on exit. confirmOpen(targetWorkSessionUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const open = _this.recentWorkSessions.sessions().filter(({ workSessionUid }) => workSessionUid !== targetWorkSessionUid); for (const { workSessionUid } of open) { if (!(yield _this.closeWorkSession(workSessionUid))) return false; } return true; })(); } closeWorkSession(uid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // The viewer flushes its edits on the way out, so the stored document is current. const session = yield _this2.workSessionDb.get(uid); if (!session) { _this2.recentWorkSessions.remove(uid); return true; } if (!(yield _this2.workSessionDb.isDraft(uid))) { if (!(yield _this2.workSessionDialog.confirmCloseOpenWorkSession(session.name))) return false; _this2.recentWorkSessions.remove(uid); return true; } if (!session.volumes.some(bundle => bundleHasWork(bundle))) { _this2.discardDraft(uid); return true; } return _this2.confirmUnsavedDraft(session); })(); } confirmUnsavedDraft(session) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessions = yield _this3.workSessionDb.find(); const result = yield _this3.workSessionDialog.unsavedWorkSessionDialog({ existingNames: workSessions.filter(({ uid }) => uid !== session.uid).map(({ name }) => name), name: session.name, warning: _this3.translate.instant('workSession.unsaved.switchMessage') }); if (!result) return false; if (result.discard) { _this3.discardDraft(session.uid); return true; } if (!result.name) return false; yield _this3.saveDraft(session, result.name); _this3.recentWorkSessions.remove(session.uid); _this3.messageService.add({ severity: 'success', summary: _this3.translate.instant('workSession.saveSuccess') }); return true; })(); } saveDraft(session, name) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this4.workSessionDb.clearDraft(session.uid); yield _this4.workSessionDb.save(_tomoverse_contracts__WEBPACK_IMPORTED_MODULE_4__.workSessionSchema.parse({ ...session, name }), { incrementVersion: true }); yield _this4.workSessionNavService.awaitPendingSync(); })(); } discardDraft(uid) { this.recentWorkSessions.remove(uid); // Best-effort: RxDB cleanup must not keep the route guard pending. this.workSessionDb.delete(uid).catch(error => { this.log.warn('Failed to discard draft work session', error); }); } static ɵfac = function WorkSessionSwitchService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionSwitchService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: WorkSessionSwitchService, factory: WorkSessionSwitchService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 82757 /*!*******************************************************************!*\ !*** ./libs/feature/src/lib/work-session/work-session.service.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionService: () => (/* binding */ WorkSessionService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/common */ 25180); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core/rxjs-interop */ 24787); /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/router */ 1286); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 98241); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 57168); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs */ 8102); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs */ 12045); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs */ 59380); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs */ 38442); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs */ 9588); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs */ 86110); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! primeng/api */ 62751); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @tomoverse/contracts */ 19875); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_store__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @tomoverse/store */ 15585); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _logging_utils__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../logging/utils */ 14337); /* harmony import */ var _protocols__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../protocols */ 61632); /* harmony import */ var _work_session_dialog_service__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./work-session-dialog.service */ 35009); const SAVE_SUCCESS_KEY = 'workSession.saveSuccess'; class WorkSessionService { log = (0,_logging_utils__WEBPACK_IMPORTED_MODULE_24__.getLogger)(WorkSessionService.name); document = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT); workSessionDb = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.WorkSessionDatabaseService); workSessionApi = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.WorkSessionApiService); authService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.AuthService); annotationFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.AnnotationFacade); chamberFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.ChamberFacade); sCurveFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.SCurveFacade); renderSettingsStore = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.renderSettingsStore); viewportStore = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.viewportStore); volumeViewerStore = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.volumeViewerStore); protocolFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.ProtocolFacade); router = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_router__WEBPACK_IMPORTED_MODULE_5__.Router); messageService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_api__WEBPACK_IMPORTED_MODULE_16__.MessageService); translate = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_14__.TranslateService); workSessionNavService = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_19__.WorkSessionNavigationService); workSessionDialog = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_work_session_dialog_service__WEBPACK_IMPORTED_MODULE_26__.WorkSessionDialogService); injector = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_1__.Injector); location = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_2__.Location); geometryFacade = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_store__WEBPACK_IMPORTED_MODULE_22__.Object3DGeometryFacade); activeUid = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "activeUid" }] : [])); setupEffects = []; unregisterFlushHandler; // Per-phase annotation bundles; the live annotation store mirrors the active one. volumes = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "volumes" }] : [])); // Active phase shows live edits; the others show their held bundle. annotationGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const seriesUid = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.workSessionDbSnapshot())?.seriesUid; if (!seriesUid) return []; const phases = this.volumeViewerStore.seriesPhasesState(seriesUid); const activePhaseId = this.volumeViewerStore.phaseSelectionState(seriesUid)?.activePhaseId; const liveAnnotations = this.annotationFacade.annotations(); const order = new Map(phases.map((phase, index) => [phase.id, index])); return this.volumes().map(bundle => { const phase = phases.find(candidate => candidate.id === bundle.phaseId); return { annotations: bundle.phaseId === activePhaseId ? liveAnnotations : bundle.annotations, identification: phase?.identification, isActive: bundle.phaseId === activePhaseId, label: phase?.label ?? bundle.phaseId, phaseId: bundle.phaseId }; }).toSorted((a, b) => (order.get(a.phaseId) ?? 0) - (order.get(b.phaseId) ?? 0)); }, ...(ngDevMode ? [{ debugName: "annotationGroups" }] : [])); chamberGroups = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const seriesUid = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.workSessionDbSnapshot())?.seriesUid; if (!seriesUid) return []; const phases = this.volumeViewerStore.seriesPhasesState(seriesUid); const activePhaseId = this.volumeViewerStore.phaseSelectionState(seriesUid)?.activePhaseId; const liveChambers = this.chamberFacade.chambers(); const order = new Map(phases.map((phase, index) => [phase.id, index])); return this.volumes().map(bundle => { const phase = phases.find(candidate => candidate.id === bundle.phaseId); return { chambers: bundle.phaseId === activePhaseId ? liveChambers : bundle.chambers, identification: phase?.identification, isActive: bundle.phaseId === activePhaseId, label: phase?.label ?? bundle.phaseId, phaseId: bundle.phaseId }; }).toSorted((a, b) => (order.get(a.phaseId) ?? 0) - (order.get(b.phaseId) ?? 0)); }, ...(ngDevMode ? [{ debugName: "chamberGroups" }] : [])); _workSessionLoaded = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "_workSessionLoaded" }] : [])); get workSessionLoaded() { return this._workSessionLoaded; } // Draft = never saved by the user; stays off the backend until the first save. _isDraft = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)(false, ...(ngDevMode ? [{ debugName: "_isDraft" }] : [])); get isDraftSession() { return this._isDraft; } annotations = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.annotationFacade.annotations(), ...(ngDevMode ? [{ debugName: "annotations" }] : [])); protocols = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.protocolFacade.exportState(), ...(ngDevMode ? [{ debugName: "protocols" }] : [])); currentName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.workSessionDbSnapshot()?.name ?? '', ...(ngDevMode ? [{ debugName: "currentName" }] : [])); resetWorkSessionLoaded() { this._workSessionLoaded.set(false); } addAttachment(creator) { const uid = this.activeUid(); if (!uid) { this.log.warn('Missing workSessionUid, attachment not created!'); return; } return this.workSessionDb.addAttachment(uid, creator); } setup(workSessionUid, studyUid, seriesUid, newWorkSessionName, storeUid = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined), newWorkSessionUid = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined)) { var _this = this; this.destroySetupEffects(); this.workSessionNavService.saveWorkSessionRequested.set(0); this.workSessionNavService.exportWorkSessionRequested.set(0); this.unregisterFlushHandler = this.workSessionNavService.registerFlushHandler(() => this.persistCurrentUiState({})); // Tracks which session uid has already been imported into the stores so // that DB snapshot emissions caused by our own debounced saves don't // overwrite live store state (e.g. crosshair intersection) the user has // moved since the save was queued. let lastLoadedUid; this.setupEffects.push((0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(() => this.activeUid.set(workSessionUid())), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessionData = _this.debouncedWorkSession(); if (!workSessionData) return; const attachments = yield _this.syncStlAttachments(workSessionData.uid, workSessionData.volumes.flatMap(({ annotations }) => annotations)); yield _this.workSessionDb.save(workSessionData, { attachments, incrementVersion: true }); })), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessionData = _this.workSessionDbSnapshot(); if (!workSessionData) return; if (workSessionData.uid === lastLoadedUid) return; lastLoadedUid = workSessionData.uid; _this._isDraft.set(yield _this.workSessionDb.isDraft(workSessionData.uid)); yield _this.loadWorkSessionFromDb(workSessionData); _this._workSessionLoaded.set(true); })), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const uid = workSessionUid(); if (uid === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.WORK_SESSION_NEW_KEY) { const store = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => storeUid()); if (!store) { _this.log.warn('Cannot create a work session, the storeUid route param is missing.'); return; } // Reset so importOtAnnotations (gated on workSessionLoaded) always waits // for the new session's loadWorkSessionFromDb, not a prior session's state. _this._workSessionLoaded.set(false); try { yield _this.createAndNavigate(studyUid(), seriesUid(), store, (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => newWorkSessionName()), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => newWorkSessionUid())); } catch (error) { // Without this, a failure here (schema mismatch, a slow/interrupted // load, etc.) leaves _workSessionLoaded stuck false forever - nothing // else ever flips it back, since that only happens once a session is // actually saved and re-read. Everything gated on it (camera/viewport // init included) would then hang indefinitely instead of recovering. _this.log.error('There was an error creating the work session', error); yield _this.router.navigate(['/volume-viewer']); } } })), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!_this.workSessionNavService.saveWorkSessionRequested()) return; yield (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this.saveWorkSession()); })), (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.effect)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!_this.workSessionNavService.exportWorkSessionRequested()) return; yield (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this.handleAction(() => _this.exportWorkSession(), undefined, 'workSession.exportError'); })); }))); } ngOnDestroy() { this.destroySetupEffects(); } workSessionDbSnapshot = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toObservable)(this.activeUid).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_13__.switchMap)(uid => { if (!uid || uid === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.WORK_SESSION_NEW_KEY) return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.of)(undefined); return this.workSessionDb.get$(uid); }), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.distinctUntilChanged)((a, b) => { if (a === undefined) return b === undefined; const { updatedAt, ...restA } = a; if (b === undefined) return a === undefined; const { updatedAt: _, ...restB } = b; return (0,rxdb__WEBPACK_IMPORTED_MODULE_17__.deepEqual)(restA, restB); })), { initialValue: undefined }); currentUIWorkSession = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { // No live capture until hydration completes: the stores are half-restored while a // session loads, and an autosave then would persist them over the saved bundles. if (!this._workSessionLoaded()) return; const workSessionSnapshot = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.workSessionDbSnapshot()); const protocolDefinitions = this.protocolFacade.exportState().definitions; const annotationSize = this.annotationFacade.annotationSize(); if (!workSessionSnapshot || workSessionSnapshot.uid === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.WORK_SESSION_NEW_KEY) { // Track the live stores so this recomputes once the session is saved; result is discarded. this.exportActiveBundle('default:0'); return; } const phaseSelection = this.volumeViewerStore.phaseSelectionState(workSessionSnapshot.seriesUid); const activePhaseId = phaseSelection?.activePhaseId ?? this.volumes()[0]?.phaseId ?? 'default:0'; const liveBundle = this.exportActiveBundle(activePhaseId); const held = this.volumes(); const volumes = held.some(({ phaseId }) => phaseId === activePhaseId) ? held.map(bundle => bundle.phaseId === activePhaseId ? liveBundle : bundle) : [...held, liveBundle]; const usedProtocols = new Set(volumes.flatMap(({ protocolData }) => protocolData.instances.map(({ protocolId }) => protocolId))); // Only store default definitions if they have been used const usedDefinitions = protocolDefinitions.filter(definition => { if (_protocols__WEBPACK_IMPORTED_MODULE_25__.DEFAULT_PROTOCOLS.some(({ id }) => id === definition.id)) { return usedProtocols.has(definition.id); } return true; }); return { annotationSize, phaseSelection, protocolDefinitions: usedDefinitions, uid: workSessionSnapshot.uid, volumes }; }, ...(ngDevMode ? [{ debugName: "currentUIWorkSession" }] : [])); exportActiveBundle(phaseId) { const renderSettings = this.renderSettingsStore.export(); const viewportCamera = this.viewportStore.export(); const { activeProtocolId, instances } = this.protocolFacade.exportState(); return { annotations: this.annotationFacade.annotations().map((annotation, index) => ({ ...annotation, displayOrder: index + 1 })), chambers: this.chamberFacade.chambers(), phaseId, protocolData: { activeProtocolId, instances }, renderSettings: { ...renderSettings }, sCurveRelativeMeasurements: this.sCurveFacade.relativeMeasurements(), sCurves: this.sCurveFacade.exportSCurves(), viewportCamera: { ...viewportCamera, intersection: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.vec3ToPosition)(viewportCamera.intersection), isocenter: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.vec3ToPosition)(viewportCamera.isocenter), matrix: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.mat3ToArray)(viewportCamera.matrix), volumeCenter: viewportCamera.volumeCenter ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.vec3ToPosition)(viewportCamera.volumeCenter) : undefined } }; } debouncedWorkSession = (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toSignal)((0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toObservable)(this.currentUIWorkSession).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_9__.distinctUntilKeyChanged)('uid'), (0,rxjs__WEBPACK_IMPORTED_MODULE_12__.skipWhile)(workSession => workSession.uid === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.WORK_SESSION_NEW_KEY), (0,rxjs__WEBPACK_IMPORTED_MODULE_13__.switchMap)(initialSession => (0,_angular_core_rxjs_interop__WEBPACK_IMPORTED_MODULE_4__.toObservable)(this.currentUIWorkSession, { injector: this.injector }).pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_10__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.filter)(workSession => workSession.uid === initialSession.uid), (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.debounceTime)(500), (0,rxjs__WEBPACK_IMPORTED_MODULE_11__.map)(uiWorkSession => { const databaseSnapshot = this.workSessionDbSnapshot(); try { return _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.workSessionSchema.parse({ ...databaseSnapshot, annotationSize: uiWorkSession.annotationSize, phaseSelection: uiWorkSession.phaseSelection, protocolDefinitions: uiWorkSession.protocolDefinitions, schemaVersion: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.WORK_SESSION_LATEST_SCHEMA, volumes: uiWorkSession.volumes }); } catch (error) { this.log.warn('parsing workSession failed', { databaseSnapshot, uiWorkSession }); throw error; } }), (0,rxjs__WEBPACK_IMPORTED_MODULE_10__.filter)(Boolean), (0,rxjs__WEBPACK_IMPORTED_MODULE_8__.distinctUntilChanged)((previous, current) => previous.annotationSize === current.annotationSize && (0,rxdb__WEBPACK_IMPORTED_MODULE_17__.deepEqual)(previous.phaseSelection, current.phaseSelection) && (0,rxdb__WEBPACK_IMPORTED_MODULE_17__.deepEqual)(previous.protocolDefinitions, current.protocolDefinitions) && (0,rxdb__WEBPACK_IMPORTED_MODULE_17__.deepEqual)(previous.volumes, current.volumes))))), { initialValue: undefined }); saveWorkSession() { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessionData = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this2.currentUIWorkSession()); const workSessionSnapshotData = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this2.workSessionDbSnapshot()); if (!workSessionData || !workSessionSnapshotData) { _this2.messageService.add({ severity: 'info', summary: _this2.translate.instant('workSession.nothingToSave') }); return; } // The direct API save below assumes the backend already knows the session. if (yield _this2.workSessionDb.isDraft(workSessionData.uid)) { yield _this2.saveDraft(workSessionData.uid); return; } const attachments = yield _this2.workSessionDb.getAttachments(workSessionData.uid); // Fetch the current remote version to determine which attachments are stored remotely. // For those ones, we don't need to pass the full attachment data, just the digest const currentRemote = yield _this2.workSessionApi.get(workSessionData.uid); const remoteAttachmentIds = new Set(Object.keys(currentRemote._attachments ?? {})); const _attachments = Object.fromEntries(yield Promise.all(attachments?.map(/*#__PURE__*/function () { var _ref7 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (attachment) { const attachmentRecord = { digest: attachment.digest, length: attachment.length, type: attachment.type }; if (!remoteAttachmentIds.has(attachment.id)) { attachmentRecord.data = yield attachment.getDataBase64(); } return [attachment.id, attachmentRecord]; }); return function (_x) { return _ref7.apply(this, arguments); }; }()) ?? [])); yield _this2.handleAction(/*#__PURE__*/(0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this2.workSessionApi.update(workSessionData.uid, _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.workSessionSchemaWithAttachments.parse({ ...workSessionSnapshotData, ...workSessionData, _attachments })); }), SAVE_SUCCESS_KEY, 'workSession.saveError'); })(); } saveDraft(uid) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const name = yield _this3.promptDraftName(uid); if (!name) return; yield _this3.finalizeDraft(uid, name); _this3.messageService.add({ severity: 'success', summary: _this3.translate.instant(SAVE_SUCCESS_KEY) }); })(); } promptDraftName(uid) { var _this4 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSessions = yield _this4.workSessionDb.find(); const currentName = workSessions.find(session => session.uid === uid)?.name; const result = yield _this4.workSessionDialog.workSessionNameDialog({ createLabel: _this4.translate.instant('common.save'), existingNames: workSessions.filter(session => session.uid !== uid).map(({ name }) => name), ...(currentName ? { name: currentName } : {}) }, _this4.translate.instant('workSession.saveDialog.header')); return result?.name; })(); } finalizeDraft(uid, name) { var _this5 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { yield _this5.workSessionDb.clearDraft(uid); yield _this5.persistCurrentUiState({ name }); _this5._isDraft.set(false); })(); } // Saves right away; the autosave lags by 500 ms and dies when the page closes. persistCurrentUiState(overrides) { var _this6 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const snapshot = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this6.workSessionDbSnapshot()); if (!snapshot) return; const uiWorkSession = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this6.currentUIWorkSession()); const workSessionData = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.workSessionSchema.parse({ ...snapshot, ...(uiWorkSession ? { annotationSize: uiWorkSession.annotationSize, phaseSelection: uiWorkSession.phaseSelection, protocolDefinitions: uiWorkSession.protocolDefinitions, volumes: uiWorkSession.volumes } : {}), schemaVersion: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.WORK_SESSION_LATEST_SCHEMA, ...overrides }); const attachments = yield _this6.syncStlAttachments(workSessionData.uid, workSessionData.volumes.flatMap(({ annotations }) => annotations)); yield _this6.workSessionDb.save(workSessionData, { attachments, incrementVersion: true }); })(); } // Keeps the stored document current for whoever closes this analysis later. flushOnExit() { var _this7 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // After sign-out the flush would never resolve and would block the exit. if (!(0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this7.authService.isAuthenticated())) return; if (!(0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this7.workSessionDbSnapshot())) return; yield _this7.workSessionNavService.flushPendingChanges(); })(); } // Closing the app takes the tab with it, so unsaved work is settled here. confirmAppClose() { var _this8 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!(0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this8.authService.isAuthenticated())) return true; const snapshot = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => _this8.workSessionDbSnapshot()); if (!snapshot) return true; const { name, uid } = snapshot; // A flush after the draft flow would write a discarded draft straight back. if (yield _this8.workSessionDb.isDraft(uid)) return _this8.confirmDraftExit({ name, uid }); yield _this8.workSessionNavService.flushPendingChanges(); return true; })(); } confirmDraftExit(draft) { var _this9 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!_this9.hasUnsavedWork()) { // Empty drafts are deleted without asking. _this9.discardDraft(draft.uid); return true; } const workSessions = yield _this9.workSessionDb.find(); const result = yield _this9.workSessionDialog.unsavedWorkSessionDialog({ existingNames: workSessions.filter(session => session.uid !== draft.uid).map(({ name }) => name), name: draft.name }); if (!result) return false; if (result.discard) { _this9.discardDraft(draft.uid); return true; } if (!result.name) return false; yield _this9.finalizeDraft(draft.uid, result.name); yield _this9.workSessionNavService.awaitPendingSync(); _this9.messageService.add({ severity: 'success', summary: _this9.translate.instant(SAVE_SUCCESS_KEY) }); return true; })(); } // Camera/render tweaks don't count. hasUnsavedWork() { return (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { const held = this.volumes(); if (this.annotationFacade.annotations().length > 0) return true; if (held.some(bundle => bundle.annotations.length > 0)) return true; if (this.chamberFacade.chambers().length > 0) return true; if (held.some(bundle => bundle.chambers.length > 0)) return true; if (this.sCurveFacade.sCurves().length > 0) return true; if (held.some(bundle => bundle.sCurves.length > 0)) return true; if (this.sCurveFacade.relativeMeasurements().length > 0) return true; if (held.some(bundle => bundle.sCurveRelativeMeasurements.length > 0)) return true; const formValueSets = [...this.protocolFacade.exportState().instances.map(({ formValues }) => formValues), ...held.flatMap(bundle => bundle.protocolData.instances.map(({ formValues }) => formValues))]; return formValueSets.some(formValues => Object.values(formValues ?? {}).some(value => Array.isArray(value) ? value.length > 0 : value !== undefined && value !== '')); }); } // Keep the marker: it also stops the deletion reaching the backend. Deletion is best-effort // because RxDB cleanup must not keep the route guard pending after the user chose Discard. discardDraft(uid) { this._isDraft.set(false); this.workSessionDb.delete(uid).catch(error => { this.log.warn('Failed to discard draft work session', error); }); } createAndNavigate(studyUid, seriesUid, storeUid, newName, uid) { var _this0 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const userId = _this0.authService.currentUser()?.accountId; if (!userId) { // Must throw, not return - the caller's catch block is what recovers // `_workSessionLoaded` from the `false` it's set to right before this call. throw new Error('Cannot create a work session: no signed-in user.'); } const workSessions = yield _this0.workSessionDb.find(); const now = new Date().toISOString(); const existingNames = workSessions.map(({ name }) => ({ name })); const generatedName = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.generateUniqueName)(existingNames, 'name', _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.ANALYSIS_BASE_NAME); const name = newName ?? generatedName; // Preserve query params (e.g. otSeriesUid) across the redirect from the temporary "new" session id; // key the starting bundle to the first selected phase (?phases=), the viewer's initial active volume. const queryString = _this0.router.url.split('?')[1] ?? ''; const initialPhaseId = new URLSearchParams(queryString).get('phases')?.split(',')[0] ?? 'default:0'; const renderSettings = { forceLowQuality: false, sCurveGraphFontSize: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_20__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE, sCurveLineWidth: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_20__.DEFAULT_S_CURVE_LINE_WIDTH, selectedVolumePresetName: 'CT-Cardiac3', selectedWindowPresetName: 'Default 1', volumeRenderPresets: [], // Will be populated on first load windowPresets: [] // Will be populated on first load }; const viewportCamera = { ax: 0, cameraDistance: -10, intersection: [0, 0, 0], isocenter: [0, 0, 0], isPosterior: false, matrix: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.INIT_CAMERA_MATRIX, showCrosshairs: true, viewportAxisMapping: { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATEBOTTOMLEFT]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATETOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.BOTTOMLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.MIDDLEMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.RIGHTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.TOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.AXIAL }, volumeCenter: undefined, zoom: 1 }; const sessionData = { annotationSize: 2, createdAt: now, createdByUid: userId, name, protocolDefinitions: [], renderSettings, schemaVersion: _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.WORK_SESSION_LATEST_SCHEMA, seriesUid, storeUid, studyUid, uid: uid ?? crypto.randomUUID(), updatedAt: now, updatedByUid: userId, version: 1, viewportCamera, volumes: [{ annotations: [], chambers: [], phaseId: initialPhaseId, protocolData: { instances: [] }, renderSettings, sCurveRelativeMeasurements: [], sCurves: [], viewportCamera }] }; const validatedSession = _tomoverse_contracts__WEBPACK_IMPORTED_MODULE_18__.workSessionSchema.parse(sessionData); // Must run before the first write, or the new session reaches the backend. yield _this0.workSessionDb.markDraft(validatedSession.uid); _this0._isDraft.set(true); yield _this0.workSessionDb.save(validatedSession); _this0.location.replaceState(`/volume-viewer/${storeUid}/${studyUid}/${seriesUid}/${validatedSession.uid}`, queryString); yield _this0.router.navigate(['/volume-viewer', storeUid, studyUid, seriesUid, validatedSession.uid], { queryParamsHandling: 'preserve', // Marks this as the create flow redirect so the route reuse strategy // keeps the viewer component alive instead of recreating it. state: { [_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.WORK_SESSION_CREATED_STATE_KEY]: true } }); })(); } loadWorkSessionFromDb(workSession) { var _this1 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { const { phaseSelection, volumes } = workSession; _this1.volumes.set(volumes); // A session always reopens on the first offered phase; only which phases are offered // survives the reload, not which one was active. const firstPhaseId = phaseSelection?.availablePhaseIds[0]; const activeBundle = volumes.find(({ phaseId }) => phaseId === firstPhaseId) ?? volumes[0]; if (phaseSelection) { _this1.volumeViewerStore.setPhaseSelection(workSession.seriesUid, { ...phaseSelection, activePhaseId: activeBundle?.phaseId ?? phaseSelection.activePhaseId }); } _this1.hydrateSessionSettings(workSession); // STL geometries are session-level attachments; load them before annotations that reference them. yield _this1.populateStlGeometries(workSession.uid); if (activeBundle) { _this1.hydrateActiveBundle(activeBundle); } _this1.protocolFacade.import({ activeProtocolId: activeBundle?.protocolData.activeProtocolId ?? activeBundle?.protocolData.instances[0]?.protocolId ?? _protocols__WEBPACK_IMPORTED_MODULE_25__.DEFAULT_PROTOCOLS[0]?.id, definitions: workSession.protocolDefinitions ?? [], instances: activeBundle?.protocolData.instances ?? [] }); // Add defaults as well for (const protocol of _protocols__WEBPACK_IMPORTED_MODULE_25__.DEFAULT_PROTOCOLS) { _this1.protocolFacade.addProtocol(protocol, true); } } catch (error) { _this1.log.error(`There was an error loading the work session`, error); yield _this1.router.navigate(['/volume-viewer']); } })(); } hydrateSessionSettings(session) { this.annotationFacade.setAnnotationSize(session.annotationSize); } hydrateActiveBundle(bundle) { const { annotations, chambers, protocolData, renderSettings, sCurveRelativeMeasurements, sCurves, viewportCamera } = bundle; this.renderSettingsStore.import({ ...renderSettings, volumeRenderPresets: renderSettings.volumeRenderPresets.map(p => ({ ...p })), windowPresets: renderSettings.windowPresets.map(p => ({ ...p })) }); this.renderSettingsStore.selectWindowPreset(renderSettings.selectedWindowPresetName); this.viewportStore.import({ ...viewportCamera, intersection: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.parsePosition)(viewportCamera.intersection), isocenter: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.parsePosition)(viewportCamera.isocenter), matrix: this.parseMatrix(viewportCamera.matrix), viewportAxisMapping: { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATEBOTTOMLEFT]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATEBOTTOMLEFT] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATETOPLEFTMAIN]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.ALTERNATETOPLEFTMAIN] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.BOTTOMLEFTMAIN]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.BOTTOMLEFTMAIN] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.MIDDLEMAIN]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.MIDDLEMAIN] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.RIGHTMAIN]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.RIGHTMAIN] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.TOPLEFTMAIN]: viewportCamera.viewportAxisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxisState.TOPLEFTMAIN] ?? _tomoverse_enums__WEBPACK_IMPORTED_MODULE_21__.ViewportAxis.AXIAL }, volumeCenter: viewportCamera.volumeCenter ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.parsePosition)(viewportCamera.volumeCenter) : undefined }); this.annotationFacade.loadAnnotations(annotations.map(({ displayOrder, ...annotation }) => annotation)); this.chamberFacade.loadChambers(chambers); // Spline-derived stubs get reconciled against the just-loaded annotations by the // s-curve store's own reactive sync effect, so this must come after loadAnnotations. this.sCurveFacade.importSCurves(sCurves); this.sCurveFacade.reorderRelativeMeasurements(sCurveRelativeMeasurements); this.protocolFacade.import({ activeProtocolId: protocolData.activeProtocolId, instances: protocolData.instances }); } requestActiveVolume(phaseId, revealAnnotationId) { this.volumeViewerStore.requestActiveVolume({ phaseId, revealAnnotationId }); } requestActiveChamberVolume(phaseId, revealChamberId) { this.volumeViewerStore.requestActiveVolume({ phaseId, revealChamberId }); } switchActiveVolume(fromPhaseId, toPhaseId) { if (fromPhaseId === toPhaseId) return; const protocolDefinitions = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => this.protocolFacade.exportState().definitions); const savedFrom = this.exportActiveBundle(fromPhaseId); const held = this.volumes().some(({ phaseId }) => phaseId === fromPhaseId) ? this.volumes().map(bundle => bundle.phaseId === fromPhaseId ? savedFrom : bundle) : [...this.volumes(), savedFrom]; // A first-visit phase inherits the current render settings and camera with no annotations, and empty protocol instances. const target = held.find(({ phaseId }) => phaseId === toPhaseId) ?? { ...this.exportActiveBundle(toPhaseId), annotations: [], chambers: [], protocolData: { instances: protocolDefinitions.map(({ id }) => ({ placeholderMappings: {}, protocolId: id })) }, sCurveRelativeMeasurements: [], sCurves: [] }; this.volumes.set(held.some(({ phaseId }) => phaseId === toPhaseId) ? held : [...held, target]); this.hydrateActiveBundle(target); } populateStlGeometries(uid) { var _this10 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const lookup = {}; const attachments = yield _this10.workSessionDb.getAttachments(uid); const stlAttachments = attachments?.filter(attachment => attachment.id.startsWith('stl:')) ?? []; for (const attachment of stlAttachments) { try { const blob = yield attachment.getData(); const geometry = yield (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.readObject3DGeometryBlob)(blob); if (geometry) { lookup[attachment.id] = geometry; } } catch (error) { console.warn(`Failed to populate geometry for ${attachment.id}`, error); } } _this10.geometryFacade.importStlGeometry(lookup); })(); } exportWorkSession() { var _this11 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const workSession = _this11.workSessionDbSnapshot(); if (!workSession) { throw new Error(`Current work session data not found.`); } try { const attachments = yield _this11.workSessionDb.getAttachments(workSession.uid); const fileName = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.formatExportFileName)(workSession.name); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.exportToJsonFile)(_this11.document, { ...workSession, _attachments: yield Promise.all((attachments ?? []).map(/*#__PURE__*/function () { var _ref9 = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (attachment) { return { data: yield attachment.getDataBase64(), digest: attachment.digest, id: attachment.id, length: attachment.length, type: attachment.type }; }); return function (_x2) { return _ref9.apply(this, arguments); }; }())) }, fileName); } catch (error) { console.error('Failed to export', error); throw error; } })(); } parseMatrix(matrix) { return gl_matrix__WEBPACK_IMPORTED_MODULE_15__.fromValues(matrix[0] ?? 0, matrix[1] ?? 0, matrix[2] ?? 0, matrix[3] ?? 0, matrix[4] ?? 0, matrix[5] ?? 0, matrix[6] ?? 0, matrix[7] ?? 0, matrix[8] ?? 0); } handleAction(action, successKey, errorKey) { var _this12 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { try { yield (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__.untracked)(action); if (successKey) { _this12.messageService.add({ severity: 'success', summary: _this12.translate.instant(successKey) }); } } catch { if (errorKey) { _this12.messageService.add({ severity: 'error', summary: _this12.translate.instant(errorKey) }); } } })(); } destroySetupEffects() { this.unregisterFlushHandler?.(); this.unregisterFlushHandler = undefined; for (const effectReference of this.setupEffects) { effectReference.destroy(); } this.setupEffects = []; } syncStlAttachments(uid, annotations) { var _this13 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const stlAnnotations = annotations.filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_20__.annotationIsStl)(annotation)); if (stlAnnotations.length === 0) return []; const currentAttachments = yield _this13.workSessionDb.getAttachments(uid); if (!currentAttachments) return; const attachments = []; const usedGeometryIds = new Set(stlAnnotations.map(stl => stl.geometryId)); const geometries = _this13.geometryFacade.exportStlGeometry(); for (const [geometryId, geometry] of Object.entries(geometries)) { // If geometry is not being used by any annotations, we can remove it if (!usedGeometryIds.has(geometryId)) continue; const existing = currentAttachments.find(att => att.id === geometryId); if (existing) { // Already present, we reuse existing data attachments.push({ data: yield existing.getData(), id: geometryId, type: existing.type }); } else { const blob = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_23__.makeObject3DGeometryBlob)(geometry); attachments.push({ data: blob, id: geometryId, type: blob.type }); } } return attachments; })(); } static ɵfac = function WorkSessionService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionService)(); }; static ɵprov = /*@__PURE__*/_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ token: WorkSessionService, factory: WorkSessionService.ɵfac }); } /***/ }, /***/ 16352 /*!****************************************!*\ !*** ./libs/post-process/src/index.ts ***! \****************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_FBO_KEY: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.MASK_FBO_KEY), /* harmony export */ MASK_PREVIEW_PASS_ID: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.MASK_PREVIEW_PASS_ID), /* harmony export */ MaskPreviewPass: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.MaskPreviewPass), /* harmony export */ OUTLINE_PASS_ID: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.OUTLINE_PASS_ID), /* harmony export */ OutlineEffectPass: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.OutlineEffectPass), /* harmony export */ vtkPostProcessPipeline: () => (/* reexport safe */ _lib__WEBPACK_IMPORTED_MODULE_0__.vtkPostProcessPipeline) /* harmony export */ }); /* harmony import */ var _lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib */ 59356); /***/ }, /***/ 19088 /*!**************************************************!*\ !*** ./libs/post-process/src/lib/debug/index.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ captureExtendedSnapshot: () => (/* reexport safe */ _post_process_state_debug__WEBPACK_IMPORTED_MODULE_0__.captureExtendedSnapshot), /* harmony export */ diagnoseDirtyState: () => (/* reexport safe */ _post_process_state_debug__WEBPACK_IMPORTED_MODULE_0__.diagnoseDirtyState), /* harmony export */ diagnoseExtendedDrift: () => (/* reexport safe */ _post_process_state_debug__WEBPACK_IMPORTED_MODULE_0__.diagnoseExtendedDrift), /* harmony export */ reportDirtyState: () => (/* reexport safe */ _post_process_state_debug__WEBPACK_IMPORTED_MODULE_0__.reportDirtyState) /* harmony export */ }); /* harmony import */ var _post_process_state_debug__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./post-process-state-debug */ 55966); /***/ }, /***/ 55966 /*!*********************************************************************!*\ !*** ./libs/post-process/src/lib/debug/post-process-state-debug.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ captureExtendedSnapshot: () => (/* binding */ captureExtendedSnapshot), /* harmony export */ diagnoseDirtyState: () => (/* binding */ diagnoseDirtyState), /* harmony export */ diagnoseExtendedDrift: () => (/* binding */ diagnoseExtendedDrift), /* harmony export */ reportDirtyState: () => (/* binding */ reportDirtyState) /* harmony export */ }); /* harmony import */ var _gl_state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../gl-state */ 86334); // WebGLBuffer/WebGLTexture instances have no human-readable identity; // without a stable id every log line prints `` and you can't // tell two distinct handles apart. const objectIds = new WeakMap(); let nextObjectId = 1; function idOf(value) { let id = objectIds.get(value); if (id === undefined) { id = nextObjectId++; objectIds.set(value, id); } return id; } function describe(value) { if (value === null) return 'null'; if (value instanceof Float32Array || value instanceof Int32Array) { return `[${[...value].join(', ')}]`; } if (Array.isArray(value)) return `[${value.join(', ')}]`; if (typeof value === 'object') { const ctor = value.constructor?.name ?? 'object'; return `<${ctor}#${idOf(value)}>`; } return String(value); } function pushIfMismatch(violations, field, actual, expected) { if (actual === expected) return; violations.push({ actual: describe(actual), expected: describe(expected), field }); } function arraysEqual(a, b) { if (a.length !== b.length) return false; for (const [index, element] of [...a].entries()) { if (element !== b[index]) return false; } return true; } function pushIfArrayMismatch(violations, field, actual, expected) { if (arraysEqual(actual, expected)) return; violations.push({ actual: describe(actual), expected: describe(expected), field }); } /** * Compares current GL state against the snapshot taken before the * passes ran. A "clean" pipeline produces an empty violation list. * * Empty array = pipeline restored state correctly. */ function diagnoseDirtyState(gl, snapshot) { const violations = []; pushIfMismatch(violations, 'BLEND enabled', gl.isEnabled(gl.BLEND), snapshot.blendEnabled); pushIfMismatch(violations, 'DEPTH_TEST enabled', gl.isEnabled(gl.DEPTH_TEST), snapshot.depthTestEnabled); pushIfMismatch(violations, 'SCISSOR_TEST enabled', gl.isEnabled(gl.SCISSOR_TEST), snapshot.scissorTestEnabled); pushIfMismatch(violations, 'CULL_FACE enabled', gl.isEnabled(gl.CULL_FACE), snapshot.cullFaceEnabled); pushIfMismatch(violations, 'STENCIL_TEST enabled', gl.isEnabled(gl.STENCIL_TEST), snapshot.stencilTestEnabled); pushIfMismatch(violations, 'BLEND_SRC_RGB', gl.getParameter(gl.BLEND_SRC_RGB), snapshot.blendSrcRgb); pushIfMismatch(violations, 'BLEND_DST_RGB', gl.getParameter(gl.BLEND_DST_RGB), snapshot.blendDstRgb); pushIfMismatch(violations, 'BLEND_EQUATION_RGB', gl.getParameter(gl.BLEND_EQUATION_RGB), snapshot.blendEquationRgb); pushIfMismatch(violations, 'DEPTH_FUNC', gl.getParameter(gl.DEPTH_FUNC), snapshot.depthFunc); pushIfMismatch(violations, 'DEPTH_WRITEMASK', gl.getParameter(gl.DEPTH_WRITEMASK), snapshot.depthMask); pushIfArrayMismatch(violations, 'COLOR_WRITEMASK', gl.getParameter(gl.COLOR_WRITEMASK), snapshot.colorWriteMask); pushIfArrayMismatch(violations, 'VIEWPORT', gl.getParameter(gl.VIEWPORT), snapshot.viewport); pushIfArrayMismatch(violations, 'SCISSOR_BOX', gl.getParameter(gl.SCISSOR_BOX), snapshot.scissorBox); pushIfMismatch(violations, 'CURRENT_PROGRAM', gl.getParameter(gl.CURRENT_PROGRAM), snapshot.program); pushIfMismatch(violations, 'VERTEX_ARRAY_BINDING', gl.getParameter(gl.VERTEX_ARRAY_BINDING), snapshot.vao); pushIfMismatch(violations, 'ARRAY_BUFFER_BINDING', gl.getParameter(gl.ARRAY_BUFFER_BINDING), snapshot.arrayBuffer); pushIfMismatch(violations, 'ELEMENT_ARRAY_BUFFER_BINDING', gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING), snapshot.elementArrayBuffer); pushIfMismatch(violations, 'DRAW_FRAMEBUFFER_BINDING', gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING), snapshot.drawFramebuffer); pushIfMismatch(violations, 'READ_FRAMEBUFFER_BINDING', gl.getParameter(gl.READ_FRAMEBUFFER_BINDING), snapshot.readFramebuffer); pushIfMismatch(violations, 'ACTIVE_TEXTURE', gl.getParameter(gl.ACTIVE_TEXTURE), snapshot.activeTexture); // Per-unit texture bindings, the most common dirty-state regression: // passes bind a scratch texture and forget to restore the previous // binding. ACTIVE_TEXTURE above only checks which unit is current; // this loop verifies what each tracked unit holds. const savedActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE); for (let index = 0; index < _gl_state__WEBPACK_IMPORTED_MODULE_0__.TEXTURE_UNITS_TO_SAVE; index++) { gl.activeTexture(gl.TEXTURE0 + index); const expected = snapshot.textureBindings[index]; if (!expected) continue; pushIfMismatch(violations, `TEXTURE_BINDING_2D unit ${index}`, gl.getParameter(gl.TEXTURE_BINDING_2D), expected.tex2D); pushIfMismatch(violations, `TEXTURE_BINDING_3D unit ${index}`, gl.getParameter(gl.TEXTURE_BINDING_3D), expected.tex3D); } gl.activeTexture(savedActiveTexture); return violations; } function reportDirtyState(passId, violations) { if (violations.length === 0) return; const lines = violations.map(v => ` • ${v.field}: actual=${v.actual} expected=${v.expected}`); console.error(`[post-process] pass "${passId}" left dirty GL state after run():\n${lines.join('\n')}`); } function captureDefaultVaoAttribs(gl, attributesToCheck = 4) { const previousVao = gl.getParameter(gl.VERTEX_ARRAY_BINDING); // eslint-disable-next-line unicorn/no-null -- WebGL uses null to bind the default VAO. gl.bindVertexArray(null); const attribs = []; for (let index = 0; index < attributesToCheck; index++) { attribs.push({ buffer: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING), enabled: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_ENABLED), offset: gl.getVertexAttribOffset(index, gl.VERTEX_ATTRIB_ARRAY_POINTER), size: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_SIZE), stride: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_STRIDE), type: gl.getVertexAttrib(index, gl.VERTEX_ATTRIB_ARRAY_TYPE) }); } gl.bindVertexArray(previousVao); return attribs; } function captureExtendedSnapshot(gl) { return { defaultVaoAttribs: captureDefaultVaoAttribs(gl), polygonOffsetFactor: gl.getParameter(gl.POLYGON_OFFSET_FACTOR), polygonOffsetUnits: gl.getParameter(gl.POLYGON_OFFSET_UNITS), stencilFunc: gl.getParameter(gl.STENCIL_FUNC), stencilRef: gl.getParameter(gl.STENCIL_REF), stencilValueMask: gl.getParameter(gl.STENCIL_VALUE_MASK), stencilWriteMask: gl.getParameter(gl.STENCIL_WRITEMASK) }; } function diagnoseDefaultVaoDrift(violations, before, after) { for (const [index, expected] of before.entries()) { const actual = after[index]; if (!actual) continue; for (const field of Object.keys(expected)) { pushIfMismatch(violations, `defaultVAO attrib ${index} ${field}`, actual[field], expected[field]); } } } function diagnoseExtendedDrift(gl, before) { const after = captureExtendedSnapshot(gl); const violations = []; for (const field of Object.keys(before)) { if (field === 'defaultVaoAttribs') continue; pushIfMismatch(violations, field, after[field], before[field]); } diagnoseDefaultVaoDrift(violations, before.defaultVaoAttribs, after.defaultVaoAttribs); return violations; } /***/ }, /***/ 68695 /*!*********************************************************!*\ !*** ./libs/post-process/src/lib/gl-state/constants.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TEXTURE_UNITS_TO_SAVE: () => (/* binding */ TEXTURE_UNITS_TO_SAVE) /* harmony export */ }); /** Number of texture units we save and restore. WebGL2 guarantees ≥32, * but vtk.js's volume mapper uses ~7 (scalar, color, opacity, label, * jitter, zBuffer) plus our mask FBO = 8. 16 leaves headroom without * paying for 32 getParameter calls per frame on every unit. */ const TEXTURE_UNITS_TO_SAVE = 16; /***/ }, /***/ 66660 /*!****************************************************************!*\ !*** ./libs/post-process/src/lib/gl-state/gl-state-capture.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ captureGLState: () => (/* binding */ captureGLState) /* harmony export */ }); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ 68695); /* harmony import */ var _gl_state_trace__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./gl-state-trace */ 37691); function captureTextureBindings(gl) { const previousActive = gl.getParameter(gl.ACTIVE_TEXTURE); const bindings = []; for (let index = 0; index < _constants__WEBPACK_IMPORTED_MODULE_0__.TEXTURE_UNITS_TO_SAVE; index++) { gl.activeTexture(gl.TEXTURE0 + index); bindings.push({ tex2D: gl.getParameter(gl.TEXTURE_BINDING_2D), tex3D: gl.getParameter(gl.TEXTURE_BINDING_3D) }); } gl.activeTexture(previousActive); return bindings; } /** Capture every piece of GL state our passes can touch. */ function captureGLState(gl) { (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'capture:entry'); const textureBindings = captureTextureBindings(gl); return { activeTexture: gl.getParameter(gl.ACTIVE_TEXTURE), arrayBuffer: gl.getParameter(gl.ARRAY_BUFFER_BINDING), blendColor: gl.getParameter(gl.BLEND_COLOR), blendDstAlpha: gl.getParameter(gl.BLEND_DST_ALPHA), blendDstRgb: gl.getParameter(gl.BLEND_DST_RGB), blendEnabled: gl.isEnabled(gl.BLEND), blendEquationAlpha: gl.getParameter(gl.BLEND_EQUATION_ALPHA), blendEquationRgb: gl.getParameter(gl.BLEND_EQUATION_RGB), blendSrcAlpha: gl.getParameter(gl.BLEND_SRC_ALPHA), blendSrcRgb: gl.getParameter(gl.BLEND_SRC_RGB), clearColor: gl.getParameter(gl.COLOR_CLEAR_VALUE), colorWriteMask: gl.getParameter(gl.COLOR_WRITEMASK), cullFaceEnabled: gl.isEnabled(gl.CULL_FACE), cullFaceMode: gl.getParameter(gl.CULL_FACE_MODE), depthFunc: gl.getParameter(gl.DEPTH_FUNC), depthMask: gl.getParameter(gl.DEPTH_WRITEMASK), depthTestEnabled: gl.isEnabled(gl.DEPTH_TEST), drawFramebuffer: gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING), elementArrayBuffer: gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING), frontFace: gl.getParameter(gl.FRONT_FACE), polygonOffsetFillEnabled: gl.isEnabled(gl.POLYGON_OFFSET_FILL), program: gl.getParameter(gl.CURRENT_PROGRAM), readFramebuffer: gl.getParameter(gl.READ_FRAMEBUFFER_BINDING), scissorBox: gl.getParameter(gl.SCISSOR_BOX), scissorTestEnabled: gl.isEnabled(gl.SCISSOR_TEST), stencilTestEnabled: gl.isEnabled(gl.STENCIL_TEST), textureBindings, vao: gl.getParameter(gl.VERTEX_ARRAY_BINDING), viewport: gl.getParameter(gl.VIEWPORT) }; } /***/ }, /***/ 88588 /*!****************************************************************!*\ !*** ./libs/post-process/src/lib/gl-state/gl-state-restore.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ restoreGLState: () => (/* binding */ restoreGLState), /* harmony export */ unbindActiveVao: () => (/* binding */ unbindActiveVao) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _gl_state_trace__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./gl-state-trace */ 37691); function setEnabled(gl, cap, enabled) { if (enabled) gl.enable(cap);else gl.disable(cap); } function liveBufferOrNull(gl, buffer) { if (!buffer) return null; return gl.isBuffer(buffer) ? buffer : null; } function restoreEnables(gl, snapshot) { setEnabled(gl, gl.BLEND, snapshot.blendEnabled); setEnabled(gl, gl.DEPTH_TEST, snapshot.depthTestEnabled); setEnabled(gl, gl.SCISSOR_TEST, snapshot.scissorTestEnabled); setEnabled(gl, gl.CULL_FACE, snapshot.cullFaceEnabled); setEnabled(gl, gl.STENCIL_TEST, snapshot.stencilTestEnabled); setEnabled(gl, gl.POLYGON_OFFSET_FILL, snapshot.polygonOffsetFillEnabled); } function restoreBlend(gl, snapshot) { gl.blendFuncSeparate(snapshot.blendSrcRgb, snapshot.blendDstRgb, snapshot.blendSrcAlpha, snapshot.blendDstAlpha); gl.blendEquationSeparate(snapshot.blendEquationRgb, snapshot.blendEquationAlpha); gl.blendColor(snapshot.blendColor[0] ?? 0, snapshot.blendColor[1] ?? 0, snapshot.blendColor[2] ?? 0, snapshot.blendColor[3] ?? 0); } function restoreDepthAndColor(gl, snapshot) { gl.depthFunc(snapshot.depthFunc); gl.depthMask(snapshot.depthMask); gl.colorMask(snapshot.colorWriteMask[0], snapshot.colorWriteMask[1], snapshot.colorWriteMask[2], snapshot.colorWriteMask[3]); gl.clearColor(snapshot.clearColor[0] ?? 0, snapshot.clearColor[1] ?? 0, snapshot.clearColor[2] ?? 0, snapshot.clearColor[3] ?? 0); } function restoreViewportAndCull(gl, snapshot) { gl.viewport(snapshot.viewport[0] ?? 0, snapshot.viewport[1] ?? 0, snapshot.viewport[2] ?? 0, snapshot.viewport[3] ?? 0); gl.scissor(snapshot.scissorBox[0] ?? 0, snapshot.scissorBox[1] ?? 0, snapshot.scissorBox[2] ?? 0, snapshot.scissorBox[3] ?? 0); gl.cullFace(snapshot.cullFaceMode); gl.frontFace(snapshot.frontFace); } function restoreTextureBindings(gl, snapshot) { // A unit can simultaneously hold a TEXTURE_2D and a TEXTURE_3D // binding, so restore both per unit. for (let index = 0; index < snapshot.textureBindings.length; index++) { gl.activeTexture(gl.TEXTURE0 + index); const bindings = snapshot.textureBindings[index]; if (bindings) { gl.bindTexture(gl.TEXTURE_2D, bindings.tex2D); gl.bindTexture(gl.TEXTURE_3D, bindings.tex3D); } } gl.activeTexture(snapshot.activeTexture); } function restoreBuffersAndProgram(gl, snapshot, node) { // ELEMENT_ARRAY_BUFFER is per-VAO state, so bind the VAO first. (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'restore:before-array-buffer'); gl.bindBuffer(gl.ARRAY_BUFFER, liveBufferOrNull(gl, snapshot.arrayBuffer)); (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'restore:after-array-buffer'); gl.bindVertexArray(snapshot.vao); (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'restore:after-bind-vao'); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, liveBufferOrNull(gl, snapshot.elementArrayBuffer)); (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'restore:after-bind-eab'); if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.getDebugFlagByName)('postProcess')) { const error = gl.getError(); if (error !== gl.NO_ERROR) { console.debug(`[gl-state-trace] restore:gl-error-after-eab-bind = 0x${error.toString(16)}`); } } gl.useProgram(snapshot.program); node.getShaderCache().setLastShaderProgramBound(null); } /** Puts every captured field back so the pipeline is transparent to vtk's next frame. */ function restoreGLState(gl, snapshot, node) { if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.getDebugFlagByName)('postProcess')) { console.debug(`[gl-state-trace] restore:snapshot vao=${(0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.idOf)(snapshot.vao)} eab=${(0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.idOf)(snapshot.elementArrayBuffer)}`); } (0,_gl_state_trace__WEBPACK_IMPORTED_MODULE_1__.traceEab)(gl, 'restore:entry'); gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, snapshot.drawFramebuffer); gl.bindFramebuffer(gl.READ_FRAMEBUFFER, snapshot.readFramebuffer); restoreEnables(gl, snapshot); restoreBlend(gl, snapshot); restoreDepthAndColor(gl, snapshot); restoreViewportAndCull(gl, snapshot); restoreTextureBindings(gl, snapshot); restoreBuffersAndProgram(gl, snapshot, node); } /** Detach vtk's VAO so passes can rebind buffers without corrupting it. */ function unbindActiveVao(gl) { gl.bindVertexArray(null); } /***/ }, /***/ 37691 /*!**************************************************************!*\ !*** ./libs/post-process/src/lib/gl-state/gl-state-trace.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ idOf: () => (/* binding */ idOf), /* harmony export */ traceEab: () => (/* binding */ traceEab) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const objectIds = new WeakMap(); let nextObjectId = 1; function idOf(value) { if (value === null) return 'null'; if (typeof value !== 'object') return String(value); let id = objectIds.get(value); if (id === undefined) { id = nextObjectId++; objectIds.set(value, id); } const ctor = value.constructor?.name ?? 'object'; return `<${ctor}#${id}>`; } /** Trace the current VAO + ELEMENT_ARRAY_BUFFER binding. */ function traceEab(gl, label) { if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.getDebugFlagByName)('postProcess')) return; const vao = gl.getParameter(gl.VERTEX_ARRAY_BINDING); const eab = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING); console.debug(`[gl-state-trace] ${label}: vao=${idOf(vao)} eab=${idOf(eab)}`); } /***/ }, /***/ 86334 /*!*****************************************************!*\ !*** ./libs/post-process/src/lib/gl-state/index.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TEXTURE_UNITS_TO_SAVE: () => (/* reexport safe */ _constants__WEBPACK_IMPORTED_MODULE_2__.TEXTURE_UNITS_TO_SAVE), /* harmony export */ captureGLState: () => (/* reexport safe */ _gl_state_capture__WEBPACK_IMPORTED_MODULE_0__.captureGLState), /* harmony export */ restoreGLState: () => (/* reexport safe */ _gl_state_restore__WEBPACK_IMPORTED_MODULE_1__.restoreGLState), /* harmony export */ unbindActiveVao: () => (/* reexport safe */ _gl_state_restore__WEBPACK_IMPORTED_MODULE_1__.unbindActiveVao) /* harmony export */ }); /* harmony import */ var _gl_state_capture__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gl-state-capture */ 66660); /* harmony import */ var _gl_state_restore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./gl-state-restore */ 88588); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./constants */ 68695); /***/ }, /***/ 59356 /*!********************************************!*\ !*** ./libs/post-process/src/lib/index.ts ***! \********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_FBO_KEY: () => (/* reexport safe */ _passes__WEBPACK_IMPORTED_MODULE_0__.MASK_FBO_KEY), /* harmony export */ MASK_PREVIEW_PASS_ID: () => (/* reexport safe */ _passes__WEBPACK_IMPORTED_MODULE_0__.MASK_PREVIEW_PASS_ID), /* harmony export */ MaskPreviewPass: () => (/* reexport safe */ _passes__WEBPACK_IMPORTED_MODULE_0__.MaskPreviewPass), /* harmony export */ OUTLINE_PASS_ID: () => (/* reexport safe */ _passes__WEBPACK_IMPORTED_MODULE_0__.OUTLINE_PASS_ID), /* harmony export */ OutlineEffectPass: () => (/* reexport safe */ _passes__WEBPACK_IMPORTED_MODULE_0__.OutlineEffectPass), /* harmony export */ vtkPostProcessPipeline: () => (/* reexport safe */ _pipeline__WEBPACK_IMPORTED_MODULE_1__.vtkPostProcessPipeline) /* harmony export */ }); /* harmony import */ var _passes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./passes */ 89431); /* harmony import */ var _pipeline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pipeline */ 39407); /***/ }, /***/ 89431 /*!***************************************************!*\ !*** ./libs/post-process/src/lib/passes/index.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_FBO_KEY: () => (/* reexport safe */ _outline__WEBPACK_IMPORTED_MODULE_1__.MASK_FBO_KEY), /* harmony export */ MASK_PREVIEW_PASS_ID: () => (/* reexport safe */ _mask_preview__WEBPACK_IMPORTED_MODULE_0__.MASK_PREVIEW_PASS_ID), /* harmony export */ MaskPreviewPass: () => (/* reexport safe */ _mask_preview__WEBPACK_IMPORTED_MODULE_0__.MaskPreviewPass), /* harmony export */ OUTLINE_PASS_ID: () => (/* reexport safe */ _outline__WEBPACK_IMPORTED_MODULE_1__.OUTLINE_PASS_ID), /* harmony export */ OutlineEffectPass: () => (/* reexport safe */ _outline__WEBPACK_IMPORTED_MODULE_1__.OutlineEffectPass) /* harmony export */ }); /* harmony import */ var _mask_preview__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mask-preview */ 97336); /* harmony import */ var _outline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./outline */ 69969); /***/ }, /***/ 97336 /*!****************************************************************!*\ !*** ./libs/post-process/src/lib/passes/mask-preview/index.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_PREVIEW_PASS_ID: () => (/* reexport safe */ _mask_preview_pass__WEBPACK_IMPORTED_MODULE_0__.MASK_PREVIEW_PASS_ID), /* harmony export */ MaskPreviewPass: () => (/* reexport safe */ _mask_preview_pass__WEBPACK_IMPORTED_MODULE_0__.MaskPreviewPass) /* harmony export */ }); /* harmony import */ var _mask_preview_pass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mask-preview-pass */ 64313); /***/ }, /***/ 64313 /*!****************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/mask-preview/mask-preview-pass.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_PREVIEW_PASS_ID: () => (/* binding */ MASK_PREVIEW_PASS_ID), /* harmony export */ MaskPreviewPass: () => (/* binding */ MaskPreviewPass) /* harmony export */ }); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils */ 71250); /* harmony import */ var _outline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../outline */ 69969); /* harmony import */ var _shaders_mask_preview_frag_glsl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/mask-preview.frag.glsl */ 92004); const MASK_PREVIEW_PASS_ID = 'debug-mask-preview'; const BORDER_PX = 2; const BORDER_RGB = [0.2, 0.85, 1]; const DEFAULT_PREVIEW_RECT = { scale: 0.3, x: 10, y: 40 }; /** Blits a shared FBO into a bordered rectangle for visual debugging. */ class MaskPreviewPass { maskKey; rect; id = MASK_PREVIEW_PASS_ID; programs; constructor(maskKey = _outline__WEBPACK_IMPORTED_MODULE_1__.MASK_FBO_KEY, rect = DEFAULT_PREVIEW_RECT) { this.maskKey = maskKey; this.rect = rect; } setRect(rect) { this.rect = rect; } shouldRun() { return this.rect.scale > 0; } run(context) { const { gl, height: parentH, width: parentW } = context; const programs = this.ensurePrograms(gl); if (!programs) return; // Same FBO the outline pass wrote into. Blank if the outline didn't run. const fb = context.getSharedFbo(this.maskKey); const previewW = Math.max(1, Math.floor(parentW * this.rect.scale)); const previewH = Math.max(1, Math.floor(parentH * this.rect.scale)); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.viewport(this.rect.x, this.rect.y, previewW, previewH); gl.disable(gl.SCISSOR_TEST); gl.disable(gl.BLEND); gl.disable(gl.DEPTH_TEST); gl.useProgram(programs.program); gl.bindVertexArray(programs.vao); fb.getColorTexture().activate(); const unit = fb.getColorTexture().getTextureUnit(); if (programs.uniforms.mask) gl.uniform1i(programs.uniforms.mask, unit); if (programs.uniforms.previewSize) { gl.uniform2f(programs.uniforms.previewSize, previewW, previewH); } if (programs.uniforms.borderPx) gl.uniform1f(programs.uniforms.borderPx, BORDER_PX); if (programs.uniforms.borderColor) { const [r, g, b] = BORDER_RGB; gl.uniform3f(programs.uniforms.borderColor, r, g, b); } gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Stop later passes from inheriting our preview-sized viewport. gl.viewport(0, 0, parentW, parentH); gl.activeTexture(gl.TEXTURE0 + unit); gl.bindTexture(gl.TEXTURE_2D, null); fb.getColorTexture().deactivate(); } delete(gl) { if (gl && this.programs) (0,_utils__WEBPACK_IMPORTED_MODULE_0__.deleteFullscreenQuad)(gl, this.programs); this.programs = undefined; } getDebugInfo() { return { maskKey: this.maskKey, rect: { ...this.rect } }; } ensurePrograms(gl) { if (this.programs) return this.programs; const quad = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.linkFullscreenQuad)(gl, _shaders_mask_preview_frag_glsl__WEBPACK_IMPORTED_MODULE_2__["default"], 'MaskPreviewPass'); if (!quad) return undefined; this.programs = { program: quad.program, uniforms: { borderColor: gl.getUniformLocation(quad.program, 'uBorderColor'), borderPx: gl.getUniformLocation(quad.program, 'uBorderPx'), mask: gl.getUniformLocation(quad.program, 'uMask'), previewSize: gl.getUniformLocation(quad.program, 'uPreviewSizePx') }, vao: quad.vao }; return this.programs; } } /***/ }, /***/ 41453 /*!*****************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/geometry/actor-metadata.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ readOutlineMetadata: () => (/* binding */ readOutlineMetadata) /* harmony export */ }); /** * Typed reader for `actor.set({ outlinable, annotationId }, true)`, * the opt-in we expect on every outline-eligible vtkActor. */ function readOutlineMetadata(actor) { const keys = actor.get('outlinable', 'annotationId'); if (!keys.outlinable || !keys.annotationId) return undefined; return { annotationId: keys.annotationId, outlinable: true }; } /***/ }, /***/ 53059 /*!*****************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/geometry/geometry-cache.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GeometryCache: () => (/* binding */ GeometryCache) /* harmony export */ }); /* harmony import */ var _mesh_upload__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mesh-upload */ 50299); /** * Per-actor VBO/EBO cache. Keyed by vtkProp; invalidated when the * underlying polydata points or polys array reference changes. */ class GeometryCache { entries = new Map(); visited = new Set(); /** Returns undefined for non-triangulated meshes or buffer-allocation failures. */ ensure(gl, actor) { const mapper = actor.getMapper(); if (!mapper) return undefined; const polyData = mapper.getInputData(); // vtk types these as `number[] | TypedArray`; mappers populate typed // arrays in practice and the buffer uploader relies on that. const points = polyData.getPoints().getData(); const polys = polyData.getPolys().getData(); if (!polys || polys.length === 0) return undefined; const cached = this.entries.get(actor); if (cached && cached.pointsRef === points && cached.polysRef === polys) { return cached; } return this.refresh(gl, actor, points, polys, cached); } markVisited(actor) { this.visited.add(actor); } /** Drop entries that weren't markVisited()'d this frame. Call after the mask pass. */ evictUnvisited(gl) { if (this.entries.size === 0) return; for (const [actor, entry] of this.entries) { if (this.visited.has(actor)) continue; this.disposeEntry(gl, entry); this.entries.delete(actor); } this.visited.clear(); } evictAll(gl) { this.visited.clear(); this.evictUnvisited(gl); } size() { return this.entries.size; } beginFrame() { this.visited.clear(); } /** Called on context loss / pass delete. */ dispose(gl) { if (gl) { for (const entry of this.entries.values()) this.disposeEntry(gl, entry); } this.entries.clear(); this.visited.clear(); } refresh(gl, actor, points, polys, previous) { const indices = (0,_mesh_upload__WEBPACK_IMPORTED_MODULE_0__.unpackTriangleIndices)(polys); if (!indices) return undefined; if (previous) this.disposeEntry(gl, previous); const buffers = (0,_mesh_upload__WEBPACK_IMPORTED_MODULE_0__.uploadGeometryBuffers)(gl, points, indices); if (!buffers) return undefined; const entry = { ebo: buffers.ebo, indexCount: indices.length, indexType: gl.UNSIGNED_INT, pointsRef: points, polysRef: polys, vbo: buffers.vbo }; this.entries.set(actor, entry); return entry; } disposeEntry(gl, entry) { gl.deleteBuffer(entry.vbo); gl.deleteBuffer(entry.ebo); } } /***/ }, /***/ 99086 /*!********************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/geometry/index.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GeometryCache: () => (/* reexport safe */ _geometry_cache__WEBPACK_IMPORTED_MODULE_1__.GeometryCache), /* harmony export */ readOutlineMetadata: () => (/* reexport safe */ _actor_metadata__WEBPACK_IMPORTED_MODULE_0__.readOutlineMetadata), /* harmony export */ unpackTriangleIndices: () => (/* reexport safe */ _mesh_upload__WEBPACK_IMPORTED_MODULE_2__.unpackTriangleIndices), /* harmony export */ uploadGeometryBuffers: () => (/* reexport safe */ _mesh_upload__WEBPACK_IMPORTED_MODULE_2__.uploadGeometryBuffers) /* harmony export */ }); /* harmony import */ var _actor_metadata__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./actor-metadata */ 41453); /* harmony import */ var _geometry_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./geometry-cache */ 53059); /* harmony import */ var _mesh_upload__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./mesh-upload */ 50299); /***/ }, /***/ 50299 /*!**************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/geometry/mesh-upload.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ unpackTriangleIndices: () => (/* binding */ unpackTriangleIndices), /* harmony export */ uploadGeometryBuffers: () => (/* binding */ uploadGeometryBuffers) /* harmony export */ }); let warnedNonTriangleCells = false; /** * vtk polydata to GL buffer upload. Non-triangulated input is logged * once and skipped. */ function unpackTriangleIndices(polys) { if (polys.length % 4 !== 0 || polys[0] !== 3) { if (!warnedNonTriangleCells) { warnedNonTriangleCells = true; console.warn('OutlineEffectPass: polydata is not triangulated (cell[0] !== 3); skipping outline.'); } return undefined; } const triangleCount = polys.length / 4; const indices = new Uint32Array(triangleCount * 3); for (let t = 0; t < triangleCount; t++) { const source = t * 4; const destination = t * 3; indices[destination] = polys[source + 1] ?? 0; indices[destination + 1] = polys[source + 2] ?? 0; indices[destination + 2] = polys[source + 3] ?? 0; } return indices; } function uploadGeometryBuffers(gl, points, indices) { const vbo = gl.createBuffer(); const ebo = gl.createBuffer(); if (!vbo || !ebo) return undefined; // BYTES_PER_ELEMENT check avoids the generic-typed-array lint that // `instanceof Float32Array` would trip. const pointsF32 = points.BYTES_PER_ELEMENT === 4 ? points : new Float32Array(points); gl.bindBuffer(gl.ARRAY_BUFFER, vbo); gl.bufferData(gl.ARRAY_BUFFER, pointsF32, gl.STATIC_DRAW); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); return { ebo, vbo }; } /***/ }, /***/ 69969 /*!***********************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/index.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_FBO_KEY: () => (/* reexport safe */ _outline_pass__WEBPACK_IMPORTED_MODULE_0__.MASK_FBO_KEY), /* harmony export */ OUTLINE_PASS_ID: () => (/* reexport safe */ _outline_pass__WEBPACK_IMPORTED_MODULE_0__.OUTLINE_PASS_ID), /* harmony export */ OutlineEffectPass: () => (/* reexport safe */ _outline_pass__WEBPACK_IMPORTED_MODULE_0__.OutlineEffectPass) /* harmony export */ }); /* harmony import */ var _outline_pass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./outline-pass */ 86161); /***/ }, /***/ 74548 /*!****************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/math/index.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ copyVtkMat: () => (/* reexport safe */ _scratch_matrices__WEBPACK_IMPORTED_MODULE_1__.copyVtkMat), /* harmony export */ makeScratch: () => (/* reexport safe */ _scratch_matrices__WEBPACK_IMPORTED_MODULE_1__.makeScratch), /* harmony export */ projectActorAabb: () => (/* reexport safe */ _projection__WEBPACK_IMPORTED_MODULE_0__.projectActorAabb), /* harmony export */ unionRect: () => (/* reexport safe */ _projection__WEBPACK_IMPORTED_MODULE_0__.unionRect) /* harmony export */ }); /* harmony import */ var _projection__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./projection */ 44139); /* harmony import */ var _scratch_matrices__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scratch-matrices */ 55179); /***/ }, /***/ 44139 /*!*********************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/math/projection.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectActorAabb: () => (/* binding */ projectActorAabb), /* harmony export */ unionRect: () => (/* binding */ unionRect) /* harmony export */ }); function at(array, index, fallback = 0) { return array[index] ?? fallback; } function readMcdcCoeffs(mcdc) { return { m0: at(mcdc, 0), m1: at(mcdc, 1), m11: at(mcdc, 11), m12: at(mcdc, 12), m13: at(mcdc, 13), m15: at(mcdc, 15, 1), m3: at(mcdc, 3), m4: at(mcdc, 4), m5: at(mcdc, 5), m7: at(mcdc, 7), m8: at(mcdc, 8), m9: at(mcdc, 9) }; } function readBounds(bounds) { return { xMax: at(bounds, 1), xMin: at(bounds, 0), yMax: at(bounds, 3), yMin: at(bounds, 2), zMax: at(bounds, 5), zMin: at(bounds, 4) }; } function projectCorner(m, x, y, z) { const cw = m.m3 * x + m.m7 * y + m.m11 * z + m.m15; if (cw <= 0) return undefined; return { ndcX: (m.m0 * x + m.m4 * y + m.m8 * z + m.m12) / cw, ndcY: (m.m1 * x + m.m5 * y + m.m9 * z + m.m13) / cw }; } function expandNdcBounds(rect, p) { if (!rect) return { maxX: p.ndcX, maxY: p.ndcY, minX: p.ndcX, minY: p.ndcY }; return { maxX: Math.max(rect.maxX, p.ndcX), maxY: Math.max(rect.maxY, p.ndcY), minX: Math.min(rect.minX, p.ndcX), minY: Math.min(rect.minY, p.ndcY) }; } // Returns undefined if any corner is behind the camera (cw <= 0). A // rect built from just the visible corners would be undersized and // clip the outline; callers treat undefined as "no scissor", not "off // screen". function projectAabbToNDC(mcdc, bounds) { const m = readMcdcCoeffs(mcdc); const b = readBounds(bounds); let rect; for (let index = 0; index < 8; index++) { const x = (index & 1) === 0 ? b.xMin : b.xMax; const y = (index & 2) === 0 ? b.yMin : b.yMax; const z = (index & 4) === 0 ? b.zMin : b.zMax; const corner = projectCorner(m, x, y, z); if (!corner) return undefined; rect = expandNdcBounds(rect, corner); } return rect; } function ndcRectToScreen(ndc, tile) { const minX = Math.max(-1, ndc.minX); const minY = Math.max(-1, ndc.minY); const maxX = Math.min(1, ndc.maxX); const maxY = Math.min(1, ndc.maxY); const px0 = tile.lowerLeftU + (minX + 1) * 0.5 * tile.usize; const py0 = tile.lowerLeftV + (minY + 1) * 0.5 * tile.vsize; const px1 = tile.lowerLeftU + (maxX + 1) * 0.5 * tile.usize; const py1 = tile.lowerLeftV + (maxY + 1) * 0.5 * tile.vsize; return { h: py1 - py0, w: px1 - px0, x: px0, y: py0 }; } /** * Project an actor's model-space AABB through MCDC into framebuffer * pixels. Pure functions; allocates 1 rect + up to 8 corner points per * call, fine for the expected ≤10 selected actors per frame. */ function projectActorAabb(mcdc, bounds, tile) { const ndc = projectAabbToNDC(mcdc, bounds); return ndc ? ndcRectToScreen(ndc, tile) : undefined; } function unionRect(accumulator, r) { if (!accumulator) return r; const x0 = Math.min(accumulator.x, r.x); const y0 = Math.min(accumulator.y, r.y); const x1 = Math.max(accumulator.x + accumulator.w, r.x + r.w); const y1 = Math.max(accumulator.y + accumulator.h, r.y + r.h); return { h: y1 - y0, w: x1 - x0, x: x0, y: y0 }; } /***/ }, /***/ 55179 /*!***************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/math/scratch-matrices.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ copyVtkMat: () => (/* binding */ copyVtkMat), /* harmony export */ makeScratch: () => (/* binding */ makeScratch) /* harmony export */ }); function makeScratch() { return { mvp: new Float32Array(16), proj: new Float32Array(16), user: new Float32Array(16), view: new Float32Array(16) }; } /** * vtk hands matrices back as number[] or typed-array-like, gl-matrix * wants Float32Array. The loop is faster than Float32Array.from for * ArrayLike sources. */ function copyVtkMat(destination, source) { if (source instanceof Float32Array) { destination.set(source); return destination; } for (let index = 0; index < 16; index++) destination[index] = source[index] ?? 0; return destination; } /***/ }, /***/ 86161 /*!******************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/outline-pass.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MASK_FBO_KEY: () => (/* binding */ MASK_FBO_KEY), /* harmony export */ OUTLINE_PASS_ID: () => (/* binding */ OUTLINE_PASS_ID), /* harmony export */ OutlineEffectPass: () => (/* binding */ OutlineEffectPass) /* harmony export */ }); /* harmony import */ var _geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./geometry */ 99086); /* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math */ 74548); /* harmony import */ var _outline_programs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./outline-programs */ 66593); /* harmony import */ var _stages__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stages */ 67681); /* harmony import */ var _state__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./state */ 53407); const DEFAULT_OUTLINE_PIXEL_WIDTH = 1; /** FBO key shared with `MaskPreviewPass` so the debug HUD reads from * the same off-screen buffer this pass writes. */ const MASK_FBO_KEY = 'outline-mask'; const OUTLINE_PASS_ID = 'object3d-outline'; /** * Screen-space selection outline for Object3D actors. * * Runs in two stages: * (1) `stages/mask-renderer` draws each selected silhouette into a * single-channel R8 mask FBO; * (2) `stages/composite-renderer` * samples the mask and paints a dilate-and-subtract ring onto the * framebuffer vtkForwardPass already filled. */ class OutlineEffectPass { id = OUTLINE_PASS_ID; cache = new _geometry__WEBPACK_IMPORTED_MODULE_0__.GeometryCache(); scratch = (0,_math__WEBPACK_IMPORTED_MODULE_1__.makeScratch)(); telemetry = new _state__WEBPACK_IMPORTED_MODULE_4__.OutlinePassTelemetry(); programs; outlinePixelWidth = DEFAULT_OUTLINE_PIXEL_WIDTH; selectedAnnotationIds = new Set(); state = 'idle'; setSelectedAnnotationIds(ids) { this.selectedAnnotationIds = ids; } setOutlinePixelWidth(px) { this.outlinePixelWidth = px; } shouldRun(context) { if (context.isHardwareSelecting) return false; const hasSelection = this.selectedAnnotationIds.size > 0; const projected = (0,_state__WEBPACK_IMPORTED_MODULE_4__.nextState)(this.state, { hasSelection }); return (0,_state__WEBPACK_IMPORTED_MODULE_4__.shouldRunInState)(projected); } run(context) { const { gl } = context; const programs = this.ensurePrograms(gl); if (!programs) return; const fb = context.getSharedFbo(MASK_FBO_KEY); (0,_stages__WEBPACK_IMPORTED_MODULE_3__.bindMaskTarget)(gl, fb, context.width, context.height); this.cache.beginFrame(); const hasSelection = this.selectedAnnotationIds.size > 0; if (!hasSelection) { this.cache.evictAll(gl); this.telemetry.reset(); this.state = 'idle'; fb.restorePreviousBindingsAndBuffers(); return; } const result = this.runMaskStage(context, programs); this.cache.evictUnvisited(gl); fb.restorePreviousBindingsAndBuffers(); this.telemetry.recordFrame({ drewThisFrame: result.drewAnything ? this.cache.size() : 0, unionAabb: result.unionAabb }); this.state = 'active'; if (!result.drewAnything) return; (0,_stages__WEBPACK_IMPORTED_MODULE_3__.runCompositePass)(context, { fb, outlinePixelWidth: this.outlinePixelWidth, program: programs.composite, unionAabb: result.unionAabb }); } getDebugInfo() { return { cachedActors: this.cache.size(), outlinePixelWidth: this.outlinePixelWidth, selectedCount: this.selectedAnnotationIds.size, state: this.state, ...this.telemetry.toDebugInfo() }; } delete(gl) { this.cache.dispose(gl); if (gl && this.programs) (0,_outline_programs__WEBPACK_IMPORTED_MODULE_2__.deletePrograms)(gl, this.programs); this.programs = undefined; } ensurePrograms(gl) { if (!this.programs) this.programs = (0,_outline_programs__WEBPACK_IMPORTED_MODULE_2__.buildPrograms)(gl); return this.programs; } runMaskStage(context, programs) { context.gl.bindVertexArray(programs.mask.vao); context.gl.useProgram(programs.mask.program); const result = (0,_stages__WEBPACK_IMPORTED_MODULE_3__.runMaskPass)(context, { cache: this.cache, isSelected: id => this.selectedAnnotationIds.has(id), program: programs.mask, scratch: this.scratch }); // eslint-disable-next-line unicorn/no-null -- WebGL uses null as the unbind sentinel. context.gl.bindVertexArray(null); return result; } } /***/ }, /***/ 66593 /*!**********************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/outline-programs.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildPrograms: () => (/* binding */ buildPrograms), /* harmony export */ deletePrograms: () => (/* binding */ deletePrograms) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ 71250); /* harmony import */ var _shaders_outline_composite_frag_glsl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/outline-composite.frag.glsl */ 89084); /* harmony import */ var _shaders_outline_mask_frag_glsl__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/outline-mask.frag.glsl */ 92183); /* harmony import */ var _shaders_outline_mask_vert_glsl__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./shaders/outline-mask.vert.glsl */ 73200); function buildMaskProgram(gl) { const program = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.linkProgram)(gl, _shaders_outline_mask_vert_glsl__WEBPACK_IMPORTED_MODULE_4__["default"], _shaders_outline_mask_frag_glsl__WEBPACK_IMPORTED_MODULE_3__["default"], 'OutlineEffectPass'); const vao = gl.createVertexArray(); if (!vao) { gl.deleteProgram(program); return undefined; } return { attribs: { position: gl.getAttribLocation(program, 'vertexMC') }, program, uniforms: { color: gl.getUniformLocation(program, 'uMaskColor'), mcdc: gl.getUniformLocation(program, 'MCDCMatrix') }, vao }; } function buildCompositeProgram(gl) { const quad = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.linkFullscreenQuad)(gl, _shaders_outline_composite_frag_glsl__WEBPACK_IMPORTED_MODULE_2__["default"], 'OutlineEffectPass'); if (!quad) return undefined; return { program: quad.program, uniforms: { mask: gl.getUniformLocation(quad.program, 'uMask'), maskSize: gl.getUniformLocation(quad.program, 'uMaskSizePx'), outlinePx: gl.getUniformLocation(quad.program, 'uOutlinePx') }, vao: quad.vao }; } /** * Builds the mask and composite GL programs and resolves attribute/ * uniform locations into typed records so call sites can stay * string-free. */ function buildPrograms(gl) { const mask = buildMaskProgram(gl); if (!mask) return undefined; const composite = buildCompositeProgram(gl); if (!composite) { gl.deleteProgram(mask.program); gl.deleteVertexArray(mask.vao); return undefined; } return { composite, mask }; } function deletePrograms(gl, programs) { gl.deleteProgram(programs.mask.program); gl.deleteVertexArray(programs.mask.vao); (0,_utils__WEBPACK_IMPORTED_MODULE_1__.deleteFullscreenQuad)(gl, programs.composite); } /***/ }, /***/ 41564 /*!*******************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/stages/composite-renderer.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ runCompositePass: () => (/* binding */ runCompositePass) /* harmony export */ }); function setCompositeRenderState(gl, width, height) { gl.viewport(0, 0, width, height); gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); gl.disable(gl.DEPTH_TEST); // Leave alpha untouched: Cornerstone blits the offscreen canvas with // source-over `drawImage`, so any alpha we wrote at outline pixels // would ghost as the actor moves. It also corrupts vtk's next-frame // x-ray composite. gl.colorMask(true, true, true, false); } function applyScissor(gl, width, height, unionAabb, outlinePixelWidth) { if (!unionAabb) return; const pad = Math.ceil(outlinePixelWidth) + 1; const sx = Math.max(0, Math.floor(unionAabb.x - pad)); const sy = Math.max(0, Math.floor(unionAabb.y - pad)); const sw = Math.min(width - sx, Math.ceil(unionAabb.w + pad * 2)); const sh = Math.min(height - sy, Math.ceil(unionAabb.h + pad * 2)); if (sw <= 0 || sh <= 0) return; gl.enable(gl.SCISSOR_TEST); gl.scissor(sx, sy, sw, sh); } function setCompositeUniforms(gl, program, maskUnit, width, height, outlinePixelWidth) { if (program.uniforms.mask) gl.uniform1i(program.uniforms.mask, maskUnit); if (program.uniforms.maskSize) gl.uniform2f(program.uniforms.maskSize, width, height); if (program.uniforms.outlinePx) gl.uniform1f(program.uniforms.outlinePx, outlinePixelWidth); } function unbindMaskTexture(gl, fb, unit) { // Stops vtk's TextureUnitManager from handing the next mapper a unit // that still points at our mask. gl.activeTexture(gl.TEXTURE0 + unit); gl.bindTexture(gl.TEXTURE_2D, null); fb.getColorTexture().deactivate(); } /** * Stage 2 of the outline pass. Reads the mask FBO, paints a coloured ring * onto the main framebuffer via one fullscreen TRIANGLE_STRIP. The scissor * is clamped to the actors' union AABB (padded) so per-pixel cost stays * proportional to selection size, not viewport area. */ function runCompositePass(context, inputs) { const { gl, height, width } = context; setCompositeRenderState(gl, width, height); gl.useProgram(inputs.program.program); gl.bindVertexArray(inputs.program.vao); applyScissor(gl, width, height, inputs.unionAabb, inputs.outlinePixelWidth); inputs.fb.getColorTexture().activate(); const maskUnit = inputs.fb.getColorTexture().getTextureUnit(); setCompositeUniforms(gl, inputs.program, maskUnit, width, height, inputs.outlinePixelWidth); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); gl.colorMask(true, true, true, true); unbindMaskTexture(gl, inputs.fb, maskUnit); } /***/ }, /***/ 67681 /*!******************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/stages/index.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ bindMaskTarget: () => (/* reexport safe */ _mask_renderer__WEBPACK_IMPORTED_MODULE_1__.bindMaskTarget), /* harmony export */ runCompositePass: () => (/* reexport safe */ _composite_renderer__WEBPACK_IMPORTED_MODULE_0__.runCompositePass), /* harmony export */ runMaskPass: () => (/* reexport safe */ _mask_renderer__WEBPACK_IMPORTED_MODULE_1__.runMaskPass) /* harmony export */ }); /* harmony import */ var _composite_renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./composite-renderer */ 41564); /* harmony import */ var _mask_renderer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mask-renderer */ 77829); /***/ }, /***/ 77829 /*!**************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/stages/mask-renderer.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ bindMaskTarget: () => (/* binding */ bindMaskTarget), /* harmony export */ runMaskPass: () => (/* binding */ runMaskPass) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var _geometry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry */ 99086); /* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../math */ 74548); function bindMaskTarget(gl, fb, width, height) { gl.bindFramebuffer(gl.FRAMEBUFFER, fb.getGLFramebuffer()); gl.disable(gl.SCISSOR_TEST); gl.viewport(0, 0, width, height); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.disable(gl.DEPTH_TEST); gl.disable(gl.BLEND); gl.disable(gl.CULL_FACE); } // vtk hands back row-major, gl-matrix expects column-major. function loadCameraMatrices(scratch, ren, oglRen) { const camera = ren.getActiveCamera(); const aspect = oglRen.getAspectRatio(); (0,_math__WEBPACK_IMPORTED_MODULE_2__.copyVtkMat)(scratch.view, camera.getViewMatrix()); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.transpose(scratch.view, scratch.view); (0,_math__WEBPACK_IMPORTED_MODULE_2__.copyVtkMat)(scratch.proj, camera.getProjectionMatrix(aspect, -1, 1)); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.transpose(scratch.proj, scratch.proj); } // MCDC Matrix - the Model-Coordinates → Display-Coordinates matrix: it takes a raw model-space vertex straight to clip space in one multiply. // MCDC = proj * view * user. view/proj were transposed in // loadCameraMatrices; userMatrix is already column-major. function composeMcdc(scratch, actor) { (0,_math__WEBPACK_IMPORTED_MODULE_2__.copyVtkMat)(scratch.user, actor.getUserMatrix()); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(scratch.mvp, scratch.view, scratch.user); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(scratch.mvp, scratch.proj, scratch.mvp); } function drawActorMask(gl, geom, program, mcdc, color) { if (program.uniforms.mcdc) gl.uniformMatrix4fv(program.uniforms.mcdc, false, mcdc); if (program.uniforms.color) gl.uniform3f(program.uniforms.color, color[0], color[1], color[2]); gl.bindBuffer(gl.ARRAY_BUFFER, geom.vbo); gl.enableVertexAttribArray(program.attribs.position); gl.vertexAttribPointer(program.attribs.position, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geom.ebo); gl.drawElements(gl.TRIANGLES, geom.indexCount, geom.indexType, 0); } function actorAabb(actor, mcdc, tile) { const mapper = actor.getMapper(); if (!mapper) return undefined; const bounds = mapper.getInputData().getBounds(); return (0,_math__WEBPACK_IMPORTED_MODULE_2__.projectActorAabb)(mcdc, bounds, tile); } function drawRendererMask(context, ren, oglRen, deps) { const tile = oglRen.getTiledSizeAndOrigin(); context.gl.viewport(tile.lowerLeftU, tile.lowerLeftV, tile.usize, tile.vsize); loadCameraMatrices(deps.scratch, ren, oglRen); let drewAnything = false; let unionAabb; for (const actor of ren.getViewProps()) { const meta = (0,_geometry__WEBPACK_IMPORTED_MODULE_1__.readOutlineMetadata)(actor); if (!meta || !deps.isSelected(meta.annotationId)) continue; const geom = deps.cache.ensure(context.gl, actor); if (!geom) continue; deps.cache.markVisited(actor); composeMcdc(deps.scratch, actor); const aabb = actorAabb(actor, deps.scratch.mvp, tile); if (aabb) unionAabb = (0,_math__WEBPACK_IMPORTED_MODULE_2__.unionRect)(unionAabb, aabb); const color = actor.getProperty().getColor(); drawActorMask(context.gl, geom, deps.program, deps.scratch.mvp, color); drewAnything = true; } return { drewAnything, unionAabb }; } /** * Stage 1 of the outline pass. Walks the scene-graph and rasterises each * selected actor's silhouette into the shared mask FBO, accumulating the * union AABB the composite scissor uses to bound per-pixel work. */ function runMaskPass(context, deps) { let drewAnything = false; let unionAabb; const renderable = context.viewNode.getRenderable(); const renderers = renderable.getRenderersByReference(); const numberLayers = renderable.getNumberOfLayers(); for (let layer = 0; layer < numberLayers; layer++) { for (const ren of renderers) { if (!ren.getDraw() || ren.getLayer() !== layer) continue; const oglRen = context.viewNode.getViewNodeFor(ren); if (!oglRen) continue; const r = drawRendererMask(context, ren, oglRen, deps); if (r.drewAnything) drewAnything = true; if (r.unionAabb) unionAabb = (0,_math__WEBPACK_IMPORTED_MODULE_2__.unionRect)(unionAabb, r.unionAabb); } } return { drewAnything, unionAabb }; } /***/ }, /***/ 53407 /*!*****************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/state/index.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OutlinePassTelemetry: () => (/* reexport safe */ _outline_telemetry__WEBPACK_IMPORTED_MODULE_1__.OutlinePassTelemetry), /* harmony export */ nextState: () => (/* reexport safe */ _outline_state__WEBPACK_IMPORTED_MODULE_0__.nextState), /* harmony export */ shouldRunInState: () => (/* reexport safe */ _outline_state__WEBPACK_IMPORTED_MODULE_0__.shouldRunInState) /* harmony export */ }); /* harmony import */ var _outline_state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./outline-state */ 83493); /* harmony import */ var _outline_telemetry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./outline-telemetry */ 66607); /***/ }, /***/ 83493 /*!*************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/state/outline-state.ts ***! \*************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ nextState: () => (/* binding */ nextState), /* harmony export */ shouldRunInState: () => (/* binding */ shouldRunInState) /* harmony export */ }); function nextState(current, inputs) { if (inputs.hasSelection) return 'active'; if (current === 'active') return 'clearing'; return 'idle'; } function shouldRunInState(state) { return state !== 'idle'; } /***/ }, /***/ 66607 /*!*****************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/state/outline-telemetry.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OutlinePassTelemetry: () => (/* binding */ OutlinePassTelemetry) /* harmony export */ }); /** * Per-frame counters surfaced through getDebugInfo(). Lives here so the * pass itself stays focused on rendering. */ class OutlinePassTelemetry { drew = 0; aabb; recordFrame(input) { this.drew = input.drewThisFrame; this.aabb = input.unionAabb; } reset() { this.drew = 0; this.aabb = undefined; } toDebugInfo() { return { drewThisFrame: this.drew, lastUnionAabb: this.aabb ? { ...this.aabb } : undefined }; } } /***/ }, /***/ 39407 /*!*****************************************************!*\ !*** ./libs/post-process/src/lib/pipeline/index.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ vtkPostProcessPipeline: () => (/* reexport safe */ _pipeline__WEBPACK_IMPORTED_MODULE_0__["default"]) /* harmony export */ }); /* harmony import */ var _pipeline__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./pipeline */ 27005); /***/ }, /***/ 27005 /*!********************************************************!*\ !*** ./libs/post-process/src/lib/pipeline/pipeline.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/macros */ 64946); /* harmony import */ var _kitware_vtk_js_Rendering_SceneGraph_RenderPass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/SceneGraph/RenderPass */ 19272); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _debug__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../debug */ 19088); /* harmony import */ var _gl_state__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../gl-state */ 86334); /* harmony import */ var _shared_fbo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./shared-fbo */ 48394); /* harmony import */ var _view_node__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./view-node */ 81495); function logDiagnostics(diagnostics) { const ran = diagnostics.filter(d => d.ran); if (ran.length === 0) return; const summary = ran.map(d => `${d.id} ${d.cpuMs.toFixed(2)}ms`).join(' · '); console.debug(`[post-process] ${summary}`); } function reportDebug(gl, snapshot, extended, anyRan, diagnostics) { if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.getDebugFlagByName)('postProcess')) return; if (anyRan) { (0,_debug__WEBPACK_IMPORTED_MODULE_3__.reportDirtyState)('post-process-pipeline (after restore)', (0,_debug__WEBPACK_IMPORTED_MODULE_3__.diagnoseDirtyState)(gl, snapshot)); if (extended) { (0,_debug__WEBPACK_IMPORTED_MODULE_3__.reportDirtyState)('post-process-pipeline (extended-fields, pass touched un-snapshotted state)', (0,_debug__WEBPACK_IMPORTED_MODULE_3__.diagnoseExtendedDrift)(gl, extended)); } } logDiagnostics(diagnostics); } function runChildren(context, passes, disabled, diagnostics) { let anyRan = false; for (const pass of passes) { if (disabled.has(pass.id)) { diagnostics.push({ cpuMs: 0, id: pass.id, ran: false }); continue; } if (!pass.shouldRun(context)) { diagnostics.push({ cpuMs: 0, id: pass.id, ran: false }); continue; } const t0 = performance.now(); pass.run(context); const cpuMs = performance.now() - t0; anyRan = true; diagnostics.push({ cpuMs, details: pass.getDebugInfo?.(), id: pass.id, ran: true }); } return anyRan; } /** * Ordered chain of `PostProcessPass` instances. Runs each pass's * shouldRun/run, then restores GL state so vtk's next frame is * undisturbed. Installed after vtkForwardPass on the render window. */ function vtkPostProcessPipeline(publicAPI, model) { model.classHierarchy.push('vtkPostProcessPipeline'); publicAPI.addPass = pass => { const existing = model.passes.findIndex(p => p.id === pass.id); if (existing === -1) { model.passes.push(pass); return; } const previous = model.passes[existing]; previous?.delete(model.ownedGl); model.passes[existing] = pass; }; publicAPI.removePass = id => { const index = model.passes.findIndex(p => p.id === id); if (index === -1) return; const pass = model.passes[index]; pass?.delete(model.ownedGl); model.passes.splice(index, 1); model.disabledPasses.delete(id); }; publicAPI.getPass = id => { return model.passes.find(p => p.id === id); }; publicAPI.setPassEnabled = (id, enabled) => { if (enabled) model.disabledPasses.delete(id);else model.disabledPasses.add(id); }; publicAPI.isPassEnabled = id => !model.disabledPasses.has(id); publicAPI.getLastFrameDiagnostics = () => model.lastFrameDiagnostics; publicAPI.traverse = viewNode => { if (model.deleted) return; const node = viewNode; const gl = node.getContext(); if (!gl) return; if (model.passes.length === 0) return; const [width, height] = node.getFramebufferSize(); if (width === 0 || height === 0) return; model.ownedGl = gl; const isHardwareSelecting = (0,_view_node__WEBPACK_IMPORTED_MODULE_6__.anyRendererSelecting)(node); const context = { getSharedFbo: key => model.fboPool.get(key, node, width, height), gl, height, isHardwareSelecting, viewNode: node, width }; // Capture before unbindActiveVao mutates anything. const snapshot = (0,_gl_state__WEBPACK_IMPORTED_MODULE_4__.captureGLState)(gl); // Debug-only: extra fields we don't restore (stencil func/mask/ref, // polygon-offset) but want to assert nothing touched. let extended; if ((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.getDebugFlagByName)('postProcess')) extended = (0,_debug__WEBPACK_IMPORTED_MODULE_3__.captureExtendedSnapshot)(gl); (0,_gl_state__WEBPACK_IMPORTED_MODULE_4__.unbindActiveVao)(gl); const diagnostics = []; const anyRan = runChildren(context, model.passes, model.disabledPasses, diagnostics); model.lastFrameDiagnostics = diagnostics; // Restore even if no pass ran: unbindActiveVao itself mutated state. (0,_gl_state__WEBPACK_IMPORTED_MODULE_4__.restoreGLState)(gl, snapshot, node); reportDebug(gl, snapshot, extended, anyRan, diagnostics); }; publicAPI.delete = () => { model.deleted = true; for (const pass of model.passes) pass.delete(model.ownedGl); model.passes.length = 0; model.disabledPasses.clear(); model.lastFrameDiagnostics = []; model.fboPool.deleteAll(); model.ownedGl = null; }; } function makeDefaults() { return { disabledPasses: new Set(), fboPool: new _shared_fbo__WEBPACK_IMPORTED_MODULE_5__.SharedFboPool(), lastFrameDiagnostics: [], ownedGl: null, passes: [] }; } function extend(publicAPI, model, initialValues = {}) { Object.assign(model, makeDefaults(), initialValues); _kitware_vtk_js_Rendering_SceneGraph_RenderPass__WEBPACK_IMPORTED_MODULE_1__["default"].extend(publicAPI, model, initialValues); vtkPostProcessPipeline(publicAPI, model); } const newInstance = _kitware_vtk_js_macros__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(extend, 'vtkPostProcessPipeline'); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ extend, newInstance }); /***/ }, /***/ 48394 /*!**********************************************************!*\ !*** ./libs/post-process/src/lib/pipeline/shared-fbo.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SharedFboPool: () => (/* binding */ SharedFboPool) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Rendering_OpenGL_Framebuffer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/OpenGL/Framebuffer */ 2573); const VTK_FILTER_LINEAR = 1; /** Lazy pool of screen-sized FBOs shared between passes in one pipeline. */ class SharedFboPool { entries = new Map(); get(key, node, width, height) { const entry = this.getOrCreate(key); entry.fb.setOpenGLRenderWindow(node); entry.fb.saveCurrentBindingsAndBuffers(); if (resizeIfNeeded(entry.fb, width, height)) entry.filterInstalled = false; if (!entry.filterInstalled) { installLinearFilter(entry.fb, node); entry.filterInstalled = true; } return entry.fb; } release(key) { this.entries.get(key)?.fb.restorePreviousBindingsAndBuffers(); } deleteAll() { for (const entry of this.entries.values()) entry.fb.delete(); this.entries.clear(); } getOrCreate(key) { let entry = this.entries.get(key); if (entry) return entry; entry = { fb: _kitware_vtk_js_Rendering_OpenGL_Framebuffer__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(), filterInstalled: false }; this.entries.set(key, entry); return entry; } } /** Returns true when the FBO was (re)created. */ function resizeIfNeeded(fb, width, height) { const size = fb.getSize(); if (size && size[0] === width && size[1] === height) return false; fb.create(width, height); fb.populateFramebuffer(); return true; } // vtkOpenGLTexture re-applies its model filter on every bind, so a bare // texParameteri is overwritten on the next activate. Setting the filter // on the texture model makes it stick. function installLinearFilter(fb, node) { const gl = node.getContext(); if (!gl) return; const tex = fb.getColorTexture(); tex.setMinificationFilter?.(VTK_FILTER_LINEAR); tex.setMagnificationFilter?.(VTK_FILTER_LINEAR); tex.activate(); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); tex.deactivate(); } /***/ }, /***/ 81495 /*!*********************************************************!*\ !*** ./libs/post-process/src/lib/pipeline/view-node.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ anyRendererSelecting: () => (/* binding */ anyRendererSelecting) /* harmony export */ }); /** True if any renderer in the window has a hardware-selector running. */ function anyRendererSelecting(node) { for (const r of node.getRenderable().getRenderersByReference()) { if (node.getViewNodeFor(r)?.getSelector?.()) return true; } return false; } /***/ }, /***/ 18089 /*!****************************************************************************!*\ !*** ./libs/post-process/src/lib/utils/fullscreen-quad/fullscreen-quad.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ deleteFullscreenQuad: () => (/* binding */ deleteFullscreenQuad), /* harmony export */ linkFullscreenQuad: () => (/* binding */ linkFullscreenQuad) /* harmony export */ }); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _shaders_fullscreen_quad_vert_glsl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./shaders/fullscreen-quad.vert.glsl */ 56053); function linkFullscreenQuad(gl, fragSource, label) { const program = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_0__.linkProgram)(gl, _shaders_fullscreen_quad_vert_glsl__WEBPACK_IMPORTED_MODULE_1__["default"], fragSource, label); const vao = gl.createVertexArray(); if (!vao) { gl.deleteProgram(program); return undefined; } return { program, vao }; } function deleteFullscreenQuad(gl, programs) { gl.deleteProgram(programs.program); gl.deleteVertexArray(programs.vao); } /***/ }, /***/ 21738 /*!******************************************************************!*\ !*** ./libs/post-process/src/lib/utils/fullscreen-quad/index.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ deleteFullscreenQuad: () => (/* reexport safe */ _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__.deleteFullscreenQuad), /* harmony export */ linkFullscreenQuad: () => (/* reexport safe */ _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__.linkFullscreenQuad) /* harmony export */ }); /* harmony import */ var _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./fullscreen-quad */ 18089); /***/ }, /***/ 71250 /*!**************************************************!*\ !*** ./libs/post-process/src/lib/utils/index.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ deleteFullscreenQuad: () => (/* reexport safe */ _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__.deleteFullscreenQuad), /* harmony export */ linkFullscreenQuad: () => (/* reexport safe */ _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__.linkFullscreenQuad) /* harmony export */ }); /* harmony import */ var _fullscreen_quad__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./fullscreen-quad */ 21738); /***/ }, /***/ 15585 /*!*********************************!*\ !*** ./libs/store/src/index.ts ***! \*********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationFacade: () => (/* reexport safe */ _lib_annotation_store_annotation_facade__WEBPACK_IMPORTED_MODULE_0__.AnnotationFacade), /* harmony export */ ChamberFacade: () => (/* reexport safe */ _lib_chamber_store_chamber_facade__WEBPACK_IMPORTED_MODULE_15__.ChamberFacade), /* harmony export */ MeasurementService: () => (/* reexport safe */ _lib_services_measurement_service__WEBPACK_IMPORTED_MODULE_14__.MeasurementService), /* harmony export */ Object3DGeometryFacade: () => (/* reexport safe */ _lib_object3d_geometry_store_object3d_geometry_facade__WEBPACK_IMPORTED_MODULE_3__.Object3DGeometryFacade), /* harmony export */ ProtocolFacade: () => (/* reexport safe */ _lib_protocol_store_protocol_facade__WEBPACK_IMPORTED_MODULE_5__.ProtocolFacade), /* harmony export */ SCurveFacade: () => (/* reexport safe */ _lib_s_curve_store_s_curve_facade__WEBPACK_IMPORTED_MODULE_8__.SCurveFacade), /* harmony export */ UiFacade: () => (/* reexport safe */ _lib_ui_store_ui_facade__WEBPACK_IMPORTED_MODULE_10__.UiFacade), /* harmony export */ annotationStore: () => (/* reexport safe */ _lib_annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_1__.annotationStore), /* harmony export */ chamberStore: () => (/* reexport safe */ _lib_chamber_store_chamber_store__WEBPACK_IMPORTED_MODULE_16__.chamberStore), /* harmony export */ cprSessionStore: () => (/* reexport safe */ _lib_cpr_session_store_cpr_session_store__WEBPACK_IMPORTED_MODULE_2__.cprSessionStore), /* harmony export */ object3DGeometryStore: () => (/* reexport safe */ _lib_object3d_geometry_store_object3d_geometry_store__WEBPACK_IMPORTED_MODULE_4__.object3DGeometryStore), /* harmony export */ protocolStore: () => (/* reexport safe */ _lib_protocol_store_protocol_store__WEBPACK_IMPORTED_MODULE_6__.protocolStore), /* harmony export */ renderSettingsStore: () => (/* reexport safe */ _lib_render_settings_store_render_settings_store__WEBPACK_IMPORTED_MODULE_7__.renderSettingsStore), /* harmony export */ sCurveStore: () => (/* reexport safe */ _lib_s_curve_store_s_curve_store__WEBPACK_IMPORTED_MODULE_9__.sCurveStore), /* harmony export */ uiStore: () => (/* reexport safe */ _lib_ui_store_ui_store__WEBPACK_IMPORTED_MODULE_11__.uiStore), /* harmony export */ viewportStore: () => (/* reexport safe */ _lib_viewport_store_viewport_store__WEBPACK_IMPORTED_MODULE_12__.viewportStore), /* harmony export */ volumeViewerStore: () => (/* reexport safe */ _lib_volume_viewer_volume_viewer_store__WEBPACK_IMPORTED_MODULE_13__.volumeViewerStore) /* harmony export */ }); /* harmony import */ var _lib_annotation_store_annotation_facade__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/annotation-store/annotation.facade */ 82856); /* harmony import */ var _lib_annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/annotation-store/annotation.store */ 12973); /* harmony import */ var _lib_cpr_session_store_cpr_session_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/cpr-session-store/cpr-session.store */ 19817); /* harmony import */ var _lib_object3d_geometry_store_object3d_geometry_facade__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/object3d-geometry-store/object3d-geometry.facade */ 52492); /* harmony import */ var _lib_object3d_geometry_store_object3d_geometry_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/object3d-geometry-store/object3d-geometry.store */ 29673); /* harmony import */ var _lib_protocol_store_protocol_facade__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/protocol-store/protocol.facade */ 79137); /* harmony import */ var _lib_protocol_store_protocol_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/protocol-store/protocol.store */ 69387); /* harmony import */ var _lib_render_settings_store_render_settings_store__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/render-settings-store/render-settings.store */ 58029); /* harmony import */ var _lib_s_curve_store_s_curve_facade__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/s-curve-store/s-curve.facade */ 988); /* harmony import */ var _lib_s_curve_store_s_curve_store__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/s-curve-store/s-curve.store */ 82425); /* harmony import */ var _lib_ui_store_ui_facade__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/ui-store/ui.facade */ 75966); /* harmony import */ var _lib_ui_store_ui_store__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/ui-store/ui.store */ 80059); /* harmony import */ var _lib_viewport_store_viewport_store__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./lib/viewport-store/viewport.store */ 96587); /* harmony import */ var _lib_volume_viewer_volume_viewer_store__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./lib/volume-viewer/volume-viewer.store */ 51217); /* harmony import */ var _lib_services_measurement_service__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/services/measurement.service */ 40959); /* harmony import */ var _lib_chamber_store_chamber_facade__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./lib/chamber-store/chamber-facade */ 8861); /* harmony import */ var _lib_chamber_store_chamber_store__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./lib/chamber-store/chamber-store */ 7282); /***/ }, /***/ 82856 /*!******************************************************************!*\ !*** ./libs/store/src/lib/annotation-store/annotation.facade.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationFacade: () => (/* binding */ AnnotationFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _object3d_geometry_store_object3d_geometry_facade__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../object3d-geometry-store/object3d-geometry.facade */ 52492); /* harmony import */ var _services_measurement_service__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../services/measurement.service */ 40959); /* harmony import */ var _viewport_store_viewport_store__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../viewport-store/viewport.store */ 96587); /* harmony import */ var _annotation_store__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./annotation.store */ 12973); class AnnotationFacade { annotationStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_annotation_store__WEBPACK_IMPORTED_MODULE_12__.annotationStore); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_3__.DialogService); measurementService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_services_measurement_service__WEBPACK_IMPORTED_MODULE_10__.MeasurementService); object3DGeometryFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_object3d_geometry_store_object3d_geometry_facade__WEBPACK_IMPORTED_MODULE_9__.Object3DGeometryFacade); translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_2__.TranslateService); viewportStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_viewport_store_viewport_store__WEBPACK_IMPORTED_MODULE_11__.viewportStore); annotations = this.annotationStore.entities; annotationMap = this.annotationStore.entityMap; annotationSize = this.annotationStore.annotationSize; selectedIds = this.annotationStore.selectedIds; selectedAnnotations = this.annotationStore.selectedAnnotations; annotationBeingCreated = this.annotationStore.annotationBeingCreated; creations$ = this.annotationStore.creations$; deletions$ = this.annotationStore.deletions$; annotationsWithMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const annotationMap = this.annotationMap(); const annotations = this.annotationStore.entities(); const measurementsMap = this.measurementService.annotationMeasurements(); return this.mapMeasurementsToAnnotations(annotations, measurementsMap, annotationMap); }, ...(ngDevMode ? [{ debugName: "annotationsWithMeasurements" }] : [])); selectedAnnotationsWithMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const annotationMap = this.annotationMap(); const selectedAnnotations = this.annotationStore.selectedAnnotations(); const measurementsMap = this.measurementService.annotationMeasurements(); return this.mapMeasurementsToAnnotations(selectedAnnotations, measurementsMap, annotationMap); }, ...(ngDevMode ? [{ debugName: "selectedAnnotationsWithMeasurements" }] : [])); addAnnotations(...annotations) { for (const annotation of annotations) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationIsObject3D)(annotation) && !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationIsStl)(annotation)) { this.object3DGeometryFacade.generateGeometry(annotation); } } this.annotationStore.addAnnotations(...annotations); } updateAnnotation(update) { this.annotationStore.updateAnnotation(this.processRelationshipUpdates(update, this.annotationMap())); } selectAnnotations(selectedIds) { this.annotationStore.selectAnnotations(selectedIds); } toggleSelectAnnotation(selectedId) { const selectedIds = this.annotationStore.selectedIds(); if (selectedIds.includes(selectedId)) { this.annotationStore.selectAnnotations([...selectedIds].filter(id => id !== selectedId)); } else { this.annotationStore.selectAnnotations([...selectedIds, selectedId]); } } selectAnnotationRange(toSelectedId) { const selectedIds = this.selectedIds(); if (selectedIds.length === 0) { // If nothing is currently selected, treat as normal select this.annotationStore.selectAnnotations([toSelectedId]); return; } const annotationIds = this.annotations().map(ann => ann.id); const firstSelectedIndex = annotationIds.findIndex(id => selectedIds.includes(id)); const lastSelectedIndex = annotationIds.findLastIndex(id => selectedIds.includes(id)); const toSelectIndex = annotationIds.indexOf(toSelectedId); // If we are already selecting the only selected annotation, no reason to do anything if (toSelectIndex === firstSelectedIndex && toSelectIndex === lastSelectedIndex) return; // If toSelectedId doesn't represent a stored annotation, we can't do anything if (toSelectIndex === -1) return; if (toSelectIndex <= firstSelectedIndex) { const newSlice = annotationIds.slice(toSelectIndex, firstSelectedIndex + 1); this.annotationStore.selectAnnotations([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } else { const newSlice = annotationIds.slice(lastSelectedIndex, toSelectIndex + 1); this.annotationStore.selectAnnotations([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } } deselectAllAnnotations() { this.annotationStore.selectAnnotations([]); } deleteAnnotations(ids) { this.annotationStore.deleteAnnotations(ids); this.object3DGeometryFacade.removeGeometries(ids); } deleteSelectedAnnotations() { const selected = this.annotationStore.selectedIds(); if (selected.length > 0) { this.deleteAnnotations(selected); } } loadAnnotations(annotations) { for (const annotation of annotations) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationIsObject3D)(annotation)) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationIsStl)(annotation)) { // The geometry will already be imported at this point, geometryId is enough this.object3DGeometryFacade.setStlGeometry(annotation.id, annotation.geometryId); } else { this.object3DGeometryFacade.generateGeometry(annotation); } } } this.annotationStore.loadAnnotations(annotations); } clearAnnotations() { this.annotationStore.loadAnnotations([]); this.object3DGeometryFacade.clear(); } setAnnotationsVisibility(ids, visible) { this.annotationStore.setAnnotationsVisibility(ids, visible); } getAnnotationById(id) { return this.annotationStore.entityMap()[id]; } creatingAnnotation(annotation) { this.annotationStore.creatingAnnotation(this.processRelationshipUpdates(annotation, this.annotationMap())); } annotationCreationComplete() { this.annotationStore.annotationCreationComplete(); } cancelAnnotationCreation() { this.annotationStore.cancelAnnotationCreation(); } isAnnotationSelected(annotation) { return this.annotationStore.isAnnotationSelected(annotation); } getDerivedAnnotationIds(sourceId) { return this.annotationStore.getDerivedAnnotationIds(sourceId); } openRenameDialog(annotation, labels) { const dialog = this.dialogService.open(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_6__.RenameDialogComponent, { closable: true, data: { cancelLabel: labels.cancelLabel, label: labels.inputLabel, maxLength: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.ANNOTATION_NAME_MAX_LENGTH, name: annotation.name, saveLabel: labels.saveLabel, structureNameSuggestions: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.ANNOTATION_STRUCTURE_NAMES[annotation.type]) }, draggable: false, header: labels.header, modal: true, resizable: false, width: '320px' }); if (!dialog) return; dialog.onClose.subscribe(newName => { if (newName && newName !== annotation.name) { this.updateAnnotation((0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__.rename)(annotation, newName)); } }); } toggleAllAnnotationsVisibility() { const annotations = this.annotationStore.entities(); const allHidden = annotations.every(annotation => annotation.hidden); this.setAnnotationsVisibility(annotations.map(({ id }) => id), allHidden); } mapMeasurementsToAnnotations(annotations, measurementsMap, allAnnotationsMap) { return annotations.map(annotation => ({ ...annotation, measurements: measurementsMap?.[annotation.id]?.map(measurement => ({ ...measurement, name: this.translate.instant(`annotationMenu.${(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.toCamelCase)(measurement.name)}`) })) ?? [], relatedNames: this.getRelatedNames(annotation, allAnnotationsMap) })); } getRelatedNames(annotation, annotationsMap) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation)) { return annotation.relationship.sourceIds.map(sourceId => annotationsMap[sourceId]?.name).filter(name => name !== undefined); } return []; } processRelationshipUpdates(annotation, annotations) { if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation) || annotation.relationship === undefined) { return annotation; } const sources = annotation.relationship.sourceIds.map(sourceId => annotations[sourceId]).filter(annotation => annotation !== undefined); if (sources.length !== annotation.relationship.sourceIds.length) { console.warn('missing sources for', annotation.id); return annotation; } return (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_7__.updateRelativeMeasurement)(annotation, sources); } setAnnotationSize(annotationSize) { this.annotationStore.setAnnotationSize(annotationSize); } goToAnnotation(id, skipNormal = false) { const annotation = this.getAnnotationById(id); if (!(0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.isRenderable)(annotation)) return; const p = (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getCentroid)(annotation); const n = skipNormal ? undefined : (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getNormal)(annotation); this.viewportStore.setCameraToPosition(p, n); } static ɵfac = function AnnotationFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AnnotationFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: AnnotationFacade, factory: AnnotationFacade.ɵfac }); } /***/ }, /***/ 12973 /*!*****************************************************************!*\ !*** ./libs/store/src/lib/annotation-store/annotation.store.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationStore: () => (/* binding */ annotationStore) /* harmony export */ }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 33242); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var _ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngrx/signals/entities */ 13106); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./utils */ 2898); const initialState = { _relationshipLookup: {}, annotationBeingCreated: undefined, annotationSize: 2, selectedIds: [] }; const annotationStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.signalStore)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.withEntities)(), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withLinkedState)(({ entityMap, selectedIds }) => ({ selectedAnnotations: () => { const ids = selectedIds(); const annotationMap = entityMap(); return ids.map(id => annotationMap[id]).filter(t => !!t); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withProps)(() => ({ _creations$: new rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject(), _deletions$: new rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject() })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withProps)(({ _creations$, _deletions$ }) => ({ creations$: _creations$.asObservable(), deletions$: _deletions$.asObservable() })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ /** * Adds a new annotation to the current collection. * @param annotation The annotation to add */ addAnnotation(annotation) { const updates = [(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(annotation)]; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation)) { const relationships = { ...store._relationshipLookup() }; for (const sourceId of annotation.relationship.sourceIds) { const lookup = relationships[sourceId] ?? []; lookup.push(annotation.id); relationships[sourceId] = lookup; } updates.push({ _relationshipLookup: relationships }); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); store._creations$.next([annotation.id]); }, addAnnotations(...annotations) { const updates = []; const relationships = { ...store._relationshipLookup() }; let relationshipsAdded = false; for (const annotation of annotations) { updates.push((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(annotation)); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation)) { for (const sourceId of annotation.relationship.sourceIds) { const lookup = relationships[sourceId] ?? []; lookup.push(annotation.id); relationships[sourceId] = lookup; relationshipsAdded = true; } } } if (relationshipsAdded) { updates.push({ _relationshipLookup: relationships }); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); store._creations$.next(annotations.map(({ id }) => id)); }, /** * Moves the annotation in the `annotationBeingCreated` slot * into the collection. */ annotationCreationComplete() { const beingCreated = store.annotationBeingCreated(); if (beingCreated) { if ((0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_5__.getValid)(beingCreated)) { const updates = [{ annotationBeingCreated: undefined }, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(beingCreated)]; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(beingCreated)) { const relationships = { ...store._relationshipLookup() }; // eslint-disable-next-line sonarjs/nested-control-flow for (const sourceId of beingCreated.relationship.sourceIds) { const lookup = relationships[sourceId] ?? []; lookup.push(beingCreated.id); relationships[sourceId] = lookup; } updates.push({ _relationshipLookup: relationships }); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); store._creations$.next([beingCreated.id]); } else { // Don't store invalid annotations this.cancelAnnotationCreation(); } } }, /** * Discards any annotation in the `annotationBeingCreated` slot. */ cancelAnnotationCreation() { const beingCreated = store.annotationBeingCreated(); if (beingCreated) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { annotationBeingCreated: undefined, selectedIds: store.selectedIds().filter(id => id !== beingCreated.id) }); } }, /** * Puts a new annotation in the `annotationBeingCreated` slot * and sets it as the currently selected annotation. * @param annotation */ creatingAnnotation(annotation) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { annotationBeingCreated: annotation, selectedIds: [annotation.id] }); }, /** * Removes the annotation corresponding to the provided id * from the collection. * @param id The id of the annotation to delete */ deleteAnnotations(ids) { const startingDeletions = ids.map(id => store.entityMap()[id]).filter(annotation => !!annotation); if (startingDeletions.length === 0) { return; } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, state => { // Recursively find all entities to delete const allDeletions = (0,_utils__WEBPACK_IMPORTED_MODULE_6__.getAllDeletions)(state, startingDeletions); // If this annotation is a relative measurement, // remove related records from the source annotations' lookups. let relationships = state._relationshipLookup; for (const annotation of allDeletions) { if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation)) { continue; } relationships = { ...relationships }; for (const sourceId of annotation.relationship.sourceIds) { const sourceRelationships = relationships[sourceId]; if (sourceRelationships) { relationships[sourceId] = sourceRelationships.filter(id => id !== annotation.id); } } delete relationships[annotation.id]; } const idsToDelete = allDeletions.map(d => d.id); if (idsToDelete.length > 0) { store._deletions$.next(idsToDelete); } return { _relationshipLookup: relationships, selectedIds: state.selectedIds.filter(index => !idsToDelete.includes(index)), ...(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.removeEntities)(idsToDelete)(state) }; }); }, /** * Return a list of all annotation ids for annotations derived from this annotation's state. * @param sourceId */ getDerivedAnnotationIds(sourceId) { return store._relationshipLookup()[sourceId] ?? []; }, /** * Returns true if the specified annotation is one that is currently selected. * @param annotation The annotation to check * @returns Whether the annotation is currently selected */ isAnnotationSelected(annotation) { return store.selectedIds().includes(annotation.id); }, /** * Replaces the full collection of annotations with the specified annotations. * @param annotations The annotation records to populate the store with. */ // eslint-disable-next-line sonarjs/cyclomatic-complexity loadAnnotations(annotations) { const annotationCount = annotations.length; const existing = store.entityMap(); const existingCount = Object.keys(existing).length; // Don't need to replace an empty set with an empty set if (annotationCount === 0 && existingCount === 0) return; let replacements = 0; // If existing records are equal, keep those so references don't change for (const [index, annotation] of annotations.entries()) { const current = existing[annotation.id]; if (current && (0,rxdb__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(current, annotation)) { annotations[index] = current; replacements++; } } // If no actual changes, no need to continue if (annotationCount > 0 && replacements === annotationCount && (0,rxdb__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(store.entities().map(annotation => annotation.id), annotations.map(annotation => annotation.id))) return; // Update relationships as needed const relationships = {}; for (const annotation of annotations) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_4__.annotationHasRelationship)(annotation)) { for (const sourceId of annotation.relationship.sourceIds) { const sourceRelationships = relationships[sourceId] ?? []; relationships[sourceId] = [...sourceRelationships, annotation.id]; } } } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.setAllEntities)(annotations), { _relationshipLookup: relationships }); }, /** * Stores the ids of which annotations are "selected". * @param selectedIds The ids of annotations to mark as selected. */ selectAnnotations(selectedIds) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { selectedIds }); }, /** * Sets the annotation size to be used when rendering. * Units are in mm (though additional scaling will be done based on zoom) */ setAnnotationSize(annotationSize) { if (store.annotationSize() !== annotationSize) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { annotationSize }); } }, /** * Sets the hidden status for a collection of annotations. */ setAnnotationsVisibility(ids, visible) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.updateEntities)({ changes: { hidden: !visible }, ids })); }, /** * Updates an existing annotation in the collection * based on the fields received. * @param update A record containing the annotation id, and fields to change. */ updateAnnotation(update) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, state => { // Recursively find all entity updates const updates = (0,_utils__WEBPACK_IMPORTED_MODULE_6__.getAllUpdates)(state, [update]); // Apply them all to a single state update let newState = state; for (const { id, ...changes } of Object.values(updates)) { newState = { ...newState, ...(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.updateEntity)({ changes: changes, id })(newState) }; } return newState; }); } }))); /***/ }, /***/ 2898 /*!******************************************************!*\ !*** ./libs/store/src/lib/annotation-store/utils.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getAllDeletions: () => (/* binding */ getAllDeletions), /* harmony export */ getAllUpdates: () => (/* binding */ getAllUpdates) /* harmony export */ }); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /** * Find all annotations to delete, including all Relative Measurements * @param state The initial store state * @param starting The initial ids to delete that were provided to the store * @returns A list of all annotations that should now be deleted */ function getAllDeletions(state, starting) { const deletions = []; const stack = [...starting]; const relationships = { ...state._relationshipLookup }; let annotation; do { annotation = stack.pop(); if (!annotation) break; if (!deletions.includes(annotation)) { deletions.push(annotation); } const relativeMeasurementIds = relationships[annotation.id] ?? []; for (const id of relativeMeasurementIds) { const relativeMeasurement = state.entityMap[id]; if (relativeMeasurement) { stack.push(relativeMeasurement); } } } while (annotation); return deletions; } function getAllUpdates(state, starting) { const updates = {}; const queue = [...starting]; const processed = new Set(); while (queue.length > 0) { const currentUpdate = queue.shift(); if (!currentUpdate) continue; if (processed.has(currentUpdate.id)) continue; // Merge and store current update const existing = state.entityMap[currentUpdate.id]; const merged = existing ? { ...existing, ...currentUpdate } : currentUpdate; updates[merged.id] = merged; processed.add(merged.id); // Process dependents const dependentIds = state._relationshipLookup[merged.id] ?? []; for (const id of dependentIds) { const updatedDependent = getUpdatedDependent(id, state, updates); if (updatedDependent) { queue.push(updatedDependent); } } } return updates; } /** * Helper to calculate the new state of a single dependent annotation */ function getUpdatedDependent(id, state, updates) { const dependent = updates[id] ?? state.entityMap[id]; if (!(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_0__.annotationHasRelationship)(dependent)) { return undefined; } const sources = dependent.relationship.sourceIds.map(sourceId => updates[sourceId] ?? state.entityMap[sourceId]).filter(s => !!s); return (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_1__.updateRelativeMeasurement)(dependent, sources); } /***/ }, /***/ 8861 /*!************************************************************!*\ !*** ./libs/store/src/lib/chamber-store/chamber-facade.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ChamberFacade: () => (/* binding */ ChamberFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _chamber_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./chamber-store */ 7282); class ChamberFacade { chamberStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_chamber_store__WEBPACK_IMPORTED_MODULE_4__.chamberStore); dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__.DialogService); chambers = this.chamberStore.entities; chamberMap = this.chamberStore.entityMap; selectedIds = this.chamberStore.selectedIds; selectedChambers = this.chamberStore.selectedChambers; creations$ = this.chamberStore.creations$; deletions$ = this.chamberStore.deletions$; addChambers(chambers) { this.chamberStore.addChambers(...chambers); } addChamber(chamber) { this.chamberStore.addChamber(chamber); } selectChambers(selectedIds) { this.chamberStore.selectChambers(selectedIds); } toggleSelectChamber(selectedId) { const selectedIds = this.chamberStore.selectedIds(); if (selectedIds.includes(selectedId)) { this.chamberStore.selectChambers([...selectedIds].filter(id => id !== selectedId)); } else { this.chamberStore.selectChambers([...selectedIds, selectedId]); } } openRenameDialog(chamber, labels) { const dialog = this.dialogService.open(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_2__.RenameDialogComponent, { closable: true, data: { cancelLabel: labels.cancelLabel, label: labels.inputLabel, maxLength: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.CHAMBER_NAME_MAX_LENGTH, name: chamber.name, saveLabel: labels.saveLabel, structureNameSuggestions: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.CHAMBER_STRUCTURE_NAMES) }, draggable: false, header: labels.header, modal: true, resizable: false, width: '320px' }); if (!dialog) return; dialog.onClose.subscribe(newName => { if (newName && newName !== chamber.name) { this.updateChamber({ ...chamber, name: newName }); } }); } updateChamber(chamber) { this.chamberStore.updateChamber(chamber); } deselectAllChambers() { this.chamberStore.selectChambers([]); } deleteChambers(ids) { this.chamberStore.deleteChambers(ids); } loadChambers(chambers) { this.chamberStore.loadChambers(chambers); } clearChambers() { this.chamberStore.loadChambers([]); } getChamberById(id) { const chamberMap = this.chamberStore.entityMap(); return chamberMap[id]; } isChamberSelected(chamber) { return this.chamberStore.isChamberSelected(chamber); } selectChamberRange(toSelectedId) { const selectedIds = this.selectedIds(); if (selectedIds.length === 0) { this.chamberStore.selectChambers([toSelectedId]); return; } const chamberIds = this.chambers().map(chamber => chamber.id); const firstSelectedIndex = chamberIds.findIndex(id => selectedIds.includes(id)); const lastSelectedIndex = chamberIds.findLastIndex(id => selectedIds.includes(id)); const toSelectIndex = chamberIds.indexOf(toSelectedId); if (toSelectIndex === firstSelectedIndex && toSelectIndex === lastSelectedIndex) return; if (toSelectIndex === -1) return; if (toSelectIndex <= firstSelectedIndex) { const newSlice = chamberIds.slice(toSelectIndex, firstSelectedIndex + 1); this.chamberStore.selectChambers([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } else { const newSlice = chamberIds.slice(lastSelectedIndex, toSelectIndex + 1); this.chamberStore.selectChambers([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } } static ɵfac = function ChamberFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChamberFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ChamberFacade, factory: ChamberFacade.ɵfac }); } /***/ }, /***/ 7282 /*!***********************************************************!*\ !*** ./libs/store/src/lib/chamber-store/chamber-store.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ chamberStore: () => (/* binding */ chamberStore) /* harmony export */ }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 33242); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var _ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngrx/signals/entities */ 13106); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxdb */ 99984); const initialState = { selectedIds: [] }; const chamberStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.signalStore)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.withEntities)(), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withLinkedState)(({ entityMap, selectedIds }) => ({ selectedChambers: () => { const ids = selectedIds(); const chamberMap = entityMap(); return ids.map(id => chamberMap[id]).filter(t => !!t); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withProps)(() => ({ _creations$: new rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject(), _deletions$: new rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject() })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withProps)(({ _creations$, _deletions$ }) => ({ creations$: _creations$.asObservable(), deletions$: _deletions$.asObservable() })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ // Add a new chamber to the store and emit its ID through the _creations$ subject. addChamber(chamber) { const updates = [(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(chamber)]; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); store._creations$.next([chamber.id]); }, addChambers(...chambers) { const updates = []; for (const chamber of chambers) { updates.push((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(chamber)); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); store._creations$.next(chambers.map(chamber => chamber.id)); }, // Remove chambers from the store based on their IDs and emit the deleted IDs through the _deletions$ subject. deleteChambers(ids) { const allDeletions = ids.map(id => store.entityMap()[id]).filter(annotation => !!annotation); if (allDeletions.length === 0) { return; } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, state => { const idsToDelete = allDeletions.map(d => d.id); if (idsToDelete.length > 0) { store._deletions$.next(idsToDelete); } return { selectedIds: state.selectedIds.filter(index => !idsToDelete.includes(index)), ...(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.removeEntities)(idsToDelete)(state) }; }); }, isChamberSelected(chamber) { return store.selectedIds().includes(chamber.id); }, loadChambers(chambers) { const chambersCount = chambers.length; const existing = store.entityMap(); const existingCount = Object.keys(existing).length; if (chambersCount === 0 && existingCount === 0) return; let replacements = 0; const normalized = chambers.map(chamber => { const existingChamber = existing[chamber.id]; if (existingChamber && (0,rxdb__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(existingChamber, chamber)) { replacements++; return existingChamber; } return chamber; }); const loadedIds = new Set(normalized.map(chamber => chamber.id)); const selectedIds = store.selectedIds().filter(id => loadedIds.has(id)); if (chambersCount > 0 && replacements === chambersCount && (0,rxdb__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(store.entities().map(chamber => chamber.id), normalized.map(chamber => chamber.id)) && (0,rxdb__WEBPACK_IMPORTED_MODULE_3__.deepEqual)(store.selectedIds(), selectedIds)) return; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.setAllEntities)(normalized)); }, selectChambers(selectedIds) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { selectedIds }); }, updateChamber(chamber) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, state => { // Recursively find all entity updates const updates = getAllUpdates(state, [chamber]); // Apply them all to a single state update let newState = state; for (const { id, ...changes } of Object.values(updates)) { newState = { ...newState, ...(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.updateEntity)({ changes: changes, id })(newState) }; } return newState; }); } }))); function getAllUpdates(state, starting) { const updates = {}; const queue = [...starting]; const processed = new Set(); while (queue.length > 0) { const currentUpdate = queue.shift(); if (!currentUpdate) continue; if (processed.has(currentUpdate.id)) continue; // Merge and store current update const existing = state.entityMap[currentUpdate.id]; const merged = existing ? { ...existing, ...currentUpdate } : currentUpdate; updates[merged.id] = merged; processed.add(merged.id); } return updates; } /***/ }, /***/ 19817 /*!*******************************************************************!*\ !*** ./libs/store/src/lib/cpr-session-store/cpr-session.store.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cprSessionStore: () => (/* binding */ cprSessionStore) /* harmony export */ }); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngrx/signals */ 84102); function defaultFractions() { return { bodyRows: [0.42, 0.58], columns: [1.3, 1], middleRows: [1, 1], topColumns: [1, 1] }; } function initialState() { return { cursorMm: 0, editState: 'review', fractions: { horizontal: defaultFractions(), vertical: defaultFractions() }, maximizedPanel: undefined, orientation: 'vertical', ribbonZoom: 1, rotationDeg: 0, verticalInversion: false }; } function wrapRotationDeg(deg) { return ((deg + 180) % 360 + 360) % 360 - 180; } /** * Substrate-free state for a curved-MPR session: what the workspace looks like, as opposed * to what `CprService` has enabled. Provided with the viewer, so it survives the workspace * remounting on every CPR entry/exit but never outlives the viewer it belongs to. */ const cprSessionStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ setCursorMm(cursorMm) { if (store.cursorMm() !== cursorMm) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { cursorMm }); }, setEditState(editState) { if (store.editState() !== editState) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { editState }); }, setMaximizedPanel(maximizedPanel) { if (store.maximizedPanel() !== maximizedPanel) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { maximizedPanel }); }, setOrientation(orientation) { if (store.orientation() !== orientation) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { orientation }); }, setRibbonZoom(ribbonZoom) { if (store.ribbonZoom() !== ribbonZoom) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ribbonZoom }); }, setRotationDeg(rotationDeg) { const wrapped = wrapRotationDeg(rotationDeg); if (store.rotationDeg() !== wrapped) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { rotationDeg: wrapped }); }, setTrackFractions(orientation, group, fractions) { const current = store.fractions(); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { fractions: { ...current, [orientation]: { ...current[orientation], [group]: fractions } } }); }, setVerticalInversion(verticalInversion) { if (store.verticalInversion() !== verticalInversion) (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { verticalInversion }); }, /** Maximize the panel, or restore if it already is — the workspace's double-click path. */ toggleMaximizedPanel(panel) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { maximizedPanel: store.maximizedPanel() === panel ? undefined : panel }); } }))); /***/ }, /***/ 52492 /*!********************************************************************************!*\ !*** ./libs/store/src/lib/object3d-geometry-store/object3d-geometry.facade.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Object3DGeometryFacade: () => (/* binding */ Object3DGeometryFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/selectors */ 27531); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _object3d_geometry_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./object3d-geometry.store */ 29673); /** * Thin facade over `Object3DGeometryStore`, exposing the geometry cache API * to consumers without leaking the signal-store implementation. */ class Object3DGeometryFacade { store = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_object3d_geometry_store__WEBPACK_IMPORTED_MODULE_3__.object3DGeometryStore); /** Reactive map of annotation id → cached geometry. */ geometryMap = this.store.geometryMap; constructor() { // Gives the `getObject3DGeometry` memoized function access to // geometry from this store. _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getObject3DGeometry.setStlFetcher( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion annotation => this.getGeometry(annotation.id)); } clear() { _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getObject3DGeometry.clear(); this.store.clear(); } getGeometry(annotationId) { return this.store.getGeometry(annotationId); } removeGeometries(ids) { for (const id of ids) { _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getObject3DGeometry.dropEntryByKey(id); } this.store.removeGeometries(ids); } removeGeometry(annotationId) { _tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getObject3DGeometry.dropEntryByKey(annotationId); this.store.removeGeometry(annotationId); } generateGeometry(annotation) { this.store.setGeometry(annotation.id, (0,_tomoverse_selectors__WEBPACK_IMPORTED_MODULE_1__.getObject3DGeometry)(annotation)); } setStlGeometry(annotationId, geometryId, geometry) { this.store.setStlGeometry(annotationId, geometryId, geometry && (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.withShell)(geometry)); } setGeometry(annotationId, geometry) { this.store.setGeometry(annotationId, geometry); } exportStlGeometry() { return this.store.exportStlGeometry(); } importStlGeometry(stlGeometryLookup) { this.store.importStlGeometry(stlGeometryLookup); } static ɵfac = function Object3DGeometryFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || Object3DGeometryFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: Object3DGeometryFacade, factory: Object3DGeometryFacade.ɵfac }); } /***/ }, /***/ 29673 /*!*******************************************************************************!*\ !*** ./libs/store/src/lib/object3d-geometry-store/object3d-geometry.store.ts ***! \*******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ object3DGeometryStore: () => (/* binding */ object3DGeometryStore) /* harmony export */ }); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngrx/signals */ 84102); const INIT_STATE = { geometryMap: {}, // Ephemeral, meant for runtime use stlGeometryLookup: {} // Will be backed up to RxDB attachments }; /** * Cache of Object3D mesh data keyed by annotation id. * * Kept separate from `AnnotationStore` because geometry is large, non-JSON * typed-array data derived from the DTO — persisting it on the annotation * would bloat emissions, break JSON round-trip, and force every DTO edit * (rename, recolor, rotate) to clone multi-MB buffers. */ const object3DGeometryStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withState)(INIT_STATE), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ clear() { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { geometryMap: {} }); }, getGeometry(annotationId) { const record = store.geometryMap()[annotationId]; switch (record?.type) { case 'direct': { return record.geometry; } case 'id': { return store.stlGeometryLookup()[record.geometryId]; } default: { return; } } }, removeGeometries(ids) { const map = { ...store.geometryMap() }; for (const id of ids) delete map[id]; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { geometryMap: map }); }, removeGeometry(annotationId) { const map = { ...store.geometryMap() }; delete map[annotationId]; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { geometryMap: map }); }, setGeometry(annotationId, geometry) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { geometryMap: { ...store.geometryMap(), [annotationId]: { geometry, type: 'direct' } } }); }, setStlGeometry(annotationId, geometryId, geometry) { const changes = { geometryMap: { ...store.geometryMap(), [annotationId]: { geometryId, type: 'id' } } }; if (geometry) { changes.stlGeometryLookup = { ...store.stlGeometryLookup(), [geometryId]: geometry }; } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, changes); } })), // State Management (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ exportStlGeometry() { return { ...store.stlGeometryLookup() }; }, importStlGeometry(stlGeometryLookup) { if (stlGeometryLookup !== store.stlGeometryLookup()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { stlGeometryLookup }); } } }))); /***/ }, /***/ 79137 /*!**************************************************************!*\ !*** ./libs/store/src/lib/protocol-store/protocol.facade.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ProtocolFacade: () => (/* binding */ ProtocolFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_store_annotation_facade__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../annotation-store/annotation.facade */ 82856); /* harmony import */ var _protocol_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./protocol.store */ 69387); class ProtocolFacade { store = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_protocol_store__WEBPACK_IMPORTED_MODULE_3__.protocolStore); annotationFacade = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_annotation_store_annotation_facade__WEBPACK_IMPORTED_MODULE_2__.AnnotationFacade); activeProtocol = this.store.activeProtocol; protocolDefinitions = this.store.definitionEntities; exportState = this.store.exportState; constructor() { const deletionSub = this.annotationFacade.deletions$.subscribe(deletedIds => { const instances = this.store.instanceEntities(); for (const instance of instances) { // Flip lookup so it's annotationId : placeholderId const annotationToPlaceholder = Object.fromEntries(Object.entries(instance.placeholderMappings).map(([k, v]) => [v, k])); const toRemove = deletedIds.map(annotationId => annotationToPlaceholder[annotationId]).filter(id => id !== undefined); if (toRemove.length > 0) { this.store.clearPlaceholders(instance.protocolId, ...toRemove); } } }); if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_1__.IS_DEV_BUILD)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any globalThis.protocolFacade = this; } (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.DestroyRef).onDestroy(() => { deletionSub.unsubscribe(); }); } addProtocol(definition, isDefault = false) { this.store.addProtocol(definition, isDefault); } removeProtocol(protocolId) { this.store.removeProtocol(protocolId); } setActiveProtocol(protocolId) { this.store.setActiveProtocol(protocolId); } fillPlaceholder(protocolId, placeholderId, annotationId) { this.store.fillPlaceholder(protocolId, placeholderId, annotationId); } clearPlaceholders(protocolId, ...placeholderIds) { this.store.clearPlaceholders(protocolId, ...placeholderIds); } clearAllPlaceholders(protocolId) { this.store.clearAllPlaceholders(protocolId); } clearFormValues(protocolId) { this.store.clearFormValues(protocolId); } setFormValues(protocolId, formValues) { this.store.setFormValues(protocolId, formValues); } import(...arguments_) { this.store.import(...arguments_); } static ɵfac = function ProtocolFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ProtocolFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: ProtocolFacade, factory: ProtocolFacade.ɵfac }); } /***/ }, /***/ 69387 /*!*************************************************************!*\ !*** ./libs/store/src/lib/protocol-store/protocol.store.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ protocolStore: () => (/* binding */ protocolStore) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var _ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngrx/signals/entities */ 13106); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/updaters */ 84249); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ 25144); const selectProtocolId = ({ protocolId }) => protocolId; const COLLECTION_DEFINITION = { collection: 'definition' }; const COLLECTION_INSTANCE = { collection: 'instance', selectId: selectProtocolId }; const INITIAL_STATE = { activeProtocolId: undefined, defaultDefinitionIds: [] }; const protocolStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.signalStore)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.withEntities)({ ...COLLECTION_DEFINITION, entity: (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.type)() }), (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.withEntities)({ ...COLLECTION_INSTANCE, entity: (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.type)() }), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withState)(INITIAL_STATE), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withComputed)(store => ({ activeProtocol: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.computed)(() => { const activeProtocolId = store.activeProtocolId(); const definitions = store.definitionEntityMap(); const instances = store.instanceEntityMap(); return { definition: activeProtocolId ? definitions[activeProtocolId] : undefined, instance: activeProtocolId ? instances[activeProtocolId] : undefined }; }) })), // Protocol Methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ addProtocol(definition, isDefault = false) { const existing = store.definitionEntityMap()[definition.id]; if (existing !== definition) { const updates = [(0,_utils__WEBPACK_IMPORTED_MODULE_5__.asUpdater)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)(definition, COLLECTION_DEFINITION))]; const instance = store.instanceEntityMap()[definition.id]; if (instance === undefined) { updates.push((0,_utils__WEBPACK_IMPORTED_MODULE_5__.asUpdater)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.addEntity)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.protocolInstance)(definition), COLLECTION_INSTANCE))); } if (isDefault) { const defaults = store.defaultDefinitionIds(); updates.push({ defaultDefinitionIds: [...defaults, definition.id] }); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); } }, removeProtocol(protocolId) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.removeEntity)(protocolId, COLLECTION_DEFINITION), (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.removeEntity)(protocolId, COLLECTION_INSTANCE)); }, setActiveProtocol(activeProtocolId) { if (store.activeProtocolId() !== activeProtocolId) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, { activeProtocolId }); } } })), // Placeholder Methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ clearAllPlaceholders(protocolId) { const instance = store.instanceEntityMap()[protocolId]; if (!instance) { // If there's no instance yet, no need to clear return; } const updated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.clearAllPlaceholderAnnotations)(instance); if (updated !== instance) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.upsertEntity)(updated, COLLECTION_INSTANCE)); } }, clearPlaceholders(protocolId, ...placeholderIds) { const instance = store.instanceEntityMap()[protocolId]; if (!instance) { // If there's no instance yet, no need to clear return; } const updated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.clearPlaceholderAnnotations)(instance, ...placeholderIds); if (updated !== instance) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.upsertEntity)(updated, COLLECTION_INSTANCE)); } }, fillPlaceholder(protocolId, placeholderId, annotationId) { const definition = store.definitionEntityMap()[protocolId]; if (!definition) { console.warn('No definition for protocolId', protocolId); return; } // Find the existing instance or create a new one. // In the future if we handle multiple instances for a protocol we will need to change this const instance = store.instanceEntityMap()[protocolId] ?? (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.protocolInstance)(definition); const updated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.setPlaceholderAnnotation)(instance, placeholderId, annotationId); if (updated !== instance) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.upsertEntity)(updated, COLLECTION_INSTANCE)); } } })), // Form methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ clearFormValues(protocolId) { const definition = store.definitionEntityMap()[protocolId]; if (!definition) { console.warn('No definition for protocolId', protocolId); return; } // Find the existing instance or create a new one. // In the future if we handle multiple instances for a protocol we will need to change this const instance = store.instanceEntityMap()[protocolId] ?? (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.protocolInstance)(definition); if (instance?.formValues !== undefined) { const updated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.clearProtocolFormValues)(instance); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.upsertEntity)(updated, COLLECTION_INSTANCE)); } }, setFormValues(protocolId, formValues) { const definition = store.definitionEntityMap()[protocolId]; if (!definition) { console.warn('No definition for protocolId', protocolId); return; } // Find the existing instance or create a new one. // In the future if we handle multiple instances for a protocol we will need to change this const instance = store.instanceEntityMap()[protocolId] ?? (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_3__.protocolInstance)(definition); const updated = (0,_tomoverse_updaters__WEBPACK_IMPORTED_MODULE_4__.setProtocolFormValues)(instance, formValues); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.upsertEntity)(updated, COLLECTION_INSTANCE)); } })), // State import/export (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withMethods)(store => ({ import(state) { const updates = []; if (state.activeProtocolId) { updates.push({ activeProtocolId: state.activeProtocolId }); } if (state.definitions) { updates.push((0,_utils__WEBPACK_IMPORTED_MODULE_5__.asUpdater)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.setAllEntities)(state.definitions, COLLECTION_DEFINITION))); } if (state.instances) { updates.push((0,_utils__WEBPACK_IMPORTED_MODULE_5__.asUpdater)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_2__.setAllEntities)(state.instances, COLLECTION_INSTANCE))); } if (updates.length > 0) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.patchState)(store, ...updates); } } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_1__.withComputed)(store => ({ // Wrap export in a signal so it can be reactively updated exportState: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.computed)(() => ({ activeProtocolId: store.activeProtocolId(), definitions: store.definitionEntities(), instances: store.instanceEntities().filter(({ formValues, placeholderMappings }) => { // Only export if it was used return Object.keys(placeholderMappings).length > 0 || Object.keys(formValues ?? {}).length > 0; }) })) }))); /***/ }, /***/ 58029 /*!***************************************************************************!*\ !*** ./libs/store/src/lib/render-settings-store/render-settings.store.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ renderSettingsStore: () => (/* binding */ renderSettingsStore) /* harmony export */ }); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const initialState = { forceLowQuality: false, sCurveGraphFontSize: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE, sCurveLineWidth: _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_S_CURVE_LINE_WIDTH, sCurveShowChamberPoints: false, selectedVolumePresetName: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC, selectedWindowPresetName: 'window1', volumeRenderPresets: [], windowPresets: [] }; const renderSettingsStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withProps)(() => ({ lowQualityTimeout: undefined })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ volumeIsDarkMode: () => { const presets = store.volumeRenderPresets(); const selected = store.selectedVolumePresetName(); const preset = presets.find(p => p.selectedPreset === selected) ?? _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC]; return preset.selectedPreset !== _tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC; }, volumeSettings: (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.deepComputed)(() => { const presets = store.volumeRenderPresets(); const selected = store.selectedVolumePresetName(); return presets.find(p => p.selectedPreset === selected) ?? _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_3__.VolumeRenderingOption.FLUOROSCOPIC]; }), windowPresetNames: () => { const presets = store.windowPresets(); return presets.map(p => p.name); }, windowSettings: (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.deepComputed)(() => { const presets = store.windowPresets(); const selected = store.selectedWindowPresetName(); return presets.find(p => p.name === selected) ?? _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_WINDOW_PRESET; }) })), // Mutation methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ addMissingVolumePresets(allPresets) { const existing = store.volumeRenderPresets(); const existingKeys = new Set(existing.map(p => p.selectedPreset)); const missing = allPresets.filter(p => !existingKeys.has(p.selectedPreset)); if (missing.length > 0) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { volumeRenderPresets: [...existing, ...missing] }); } }, resetRendererSettings() { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ...initialState }); }, selectVolumePreset(name) { if (name !== store.selectedVolumePresetName() && store.volumeRenderPresets().some(p => p.selectedPreset === name)) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { selectedVolumePresetName: name }); } }, selectWindowPreset(name) { if (name !== store.selectedWindowPresetName() && store.windowPresets().some(p => p.name === name)) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { selectedWindowPresetName: name }); } }, setLowQuality(forceLowQuality) { const current = store.forceLowQuality(); if (forceLowQuality !== current) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { forceLowQuality }); } }, setSCurveGraphFontSize(sCurveGraphFontSize) { if (sCurveGraphFontSize !== store.sCurveGraphFontSize()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveGraphFontSize }); } }, setSCurveLineWidth(sCurveLineWidth) { if (sCurveLineWidth !== store.sCurveLineWidth()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveLineWidth }); } }, setSCurveShowChamberPoints(sCurveShowChamberPoints) { if (sCurveShowChamberPoints !== store.sCurveShowChamberPoints()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveShowChamberPoints }); } }, setVolumePresets(volumeRenderPresets) { const defaultPreset = volumeRenderPresets.find(p => p.selectedPreset === _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_VOLUME_RENDERING_PRESET) ?? volumeRenderPresets[0]; const selectedVolumePresetName = defaultPreset?.selectedPreset ?? ''; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { selectedVolumePresetName, volumeRenderPresets }); }, setWindowPresets(windowPresets) { const selectedWindowPresetName = windowPresets[0]?.name ?? ''; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { selectedWindowPresetName, windowPresets }); }, updateCustomPreset(value) { const presets = store.windowPresets(); const existingIndex = presets.findIndex(p => p.name === 'Custom'); const current = store.windowSettings(); const updated = { ...current, ...value }; // Skip updates where neither value changes. We especially want this because // otherwise a feedback loop from forms can make us set the preset to Custom // when selecting an existing preset. if (current.level === updated.level && current.width === updated.width) { return; } const windowPresets = [...store.windowPresets()]; if (existingIndex === -1) { const update = { ..._tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_WINDOW_PRESET, name: 'Custom', ...value }; windowPresets.unshift(update); } else { const update = { ...windowPresets[existingIndex], ...value }; windowPresets[existingIndex] = update; } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { selectedWindowPresetName: 'Custom', windowPresets }); }, updateVolumeSettings(settings) { const current = store.volumeSettings(); const updated = { ...current, ...settings }; if ((0,rxdb__WEBPACK_IMPORTED_MODULE_1__.deepEqual)(current, updated)) return; //get current state to update the volume render store with the new preset value const presets = store.volumeRenderPresets(); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { volumeRenderPresets: presets.map(preset => preset.selectedPreset === updated.selectedPreset ? updated : preset) }); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ lowQualityWithTimeout(timeoutMs = 200) { if (store.lowQualityTimeout) { clearTimeout(store.lowQualityTimeout); store.lowQualityTimeout = undefined; } store.setLowQuality(true); store.lowQualityTimeout = setTimeout(() => { store.setLowQuality(false); }, timeoutMs); } })), // State management methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ import(state) { // Don't import empty windowPresets, // this would overwrite the initially loaded presets if (state.windowPresets?.length === 0) { delete state.selectedWindowPresetName; delete state.windowPresets; } if (state.volumeRenderPresets?.length === 0) { delete state.selectedVolumePresetName; delete state.volumeRenderPresets; } if (state.volumeRenderPresets) { const existingKeys = new Set(state.volumeRenderPresets.map(p => p.selectedPreset)); const missing = Object.values(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.VOLUME_RENDERING_PRESETS).filter(p => !existingKeys.has(p.selectedPreset)); if (missing.length > 0) { state = { ...state, volumeRenderPresets: [...state.volumeRenderPresets, ...missing] }; } } if (Object.keys(state).length > 0) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ...state }); } } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ export: () => ({ sCurveGraphFontSize: store.sCurveGraphFontSize(), sCurveLineWidth: store.sCurveLineWidth(), selectedVolumePresetName: store.selectedVolumePresetName(), selectedWindowPresetName: store.selectedWindowPresetName(), volumeRenderPresets: [...store.volumeRenderPresets()], windowPresets: [...store.windowPresets()] }) }))); /***/ }, /***/ 988 /*!************************************************************!*\ !*** ./libs/store/src/lib/s-curve-store/s-curve.facade.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveFacade: () => (/* binding */ SCurveFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_ui__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/ui */ 79048); /* harmony import */ var _s_curve_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./s-curve.store */ 82425); class SCurveFacade { dialogService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__.DialogService); sCurveStore = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_s_curve_store__WEBPACK_IMPORTED_MODULE_4__.sCurveStore); relativeMeasurements = this.sCurveStore.relativeMeasurements; sCurves = this.sCurveStore.sCurves; selectedIds = this.sCurveStore.selectedIds; selectedSCurves = this.sCurveStore.selectedSCurves; addRelativeMeasurement(measurement) { this.sCurveStore.addRelativeMeasurement(measurement); } addSCurve(sCurve) { this.sCurveStore.addSCurve(sCurve); } deleteSCurves(ids) { if (ids.length > 0) { this.sCurveStore.deleteSCurves(ids); } } /** Curves/stubs only - see `relativeMeasurements()` for the persisted subset of * relative measurements, which round-trip separately. */ exportSCurves() { return this.sCurveStore.export(); } importSCurves(sCurves) { this.sCurveStore.import(sCurves); } openRenameDialog(sCurve, labels) { const dialog = this.dialogService.open(_tomoverse_ui__WEBPACK_IMPORTED_MODULE_3__.RenameDialogComponent, { closable: true, data: { cancelLabel: labels.cancelLabel, label: labels.inputLabel, name: sCurve.name, saveLabel: labels.saveLabel }, draggable: false, header: labels.header, modal: true, resizable: false, width: '320px' }); if (!dialog) return; dialog.onClose.subscribe(newName => { if (!newName || newName === sCurve.name) return; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.sCurveIsRelativeMeasurement)(sCurve)) { this.updateRelativeMeasurement({ id: sCurve.id, name: newName }); } else { this.updateSCurve({ id: sCurve.id, name: newName }); } }); } updateSCurve(update) { this.sCurveStore.updateSCurve(update); } updateRelativeMeasurement(update) { this.sCurveStore.updateRelativeMeasurement(update); } loadSCurves(sCurves) { this.sCurveStore.loadSCurves(sCurves); } reorderRelativeMeasurements(measurements) { this.sCurveStore.reorderRelativeMeasurements(measurements); } selectSCurves(selectedIds) { this.sCurveStore.selectSCurves(selectedIds); } toggleSelectSCurve(selectedId) { const selectedIds = this.sCurveStore.selectedIds(); if (selectedIds.includes(selectedId)) { this.sCurveStore.selectSCurves([...selectedIds].filter(id => id !== selectedId)); } else { this.sCurveStore.selectSCurves([...selectedIds, selectedId]); } } selectSCurvesRange(toSelectedId) { const selectedIds = this.selectedIds(); if (selectedIds.length === 0) { // If nothing is currently selected, treat as normal select this.sCurveStore.selectSCurves([toSelectedId]); return; } const sCurveIds = this.sCurves().map(({ id }) => id); const firstSelectedIndex = sCurveIds.findIndex(id => selectedIds.includes(id)); const lastSelectedIndex = sCurveIds.findLastIndex(id => selectedIds.includes(id)); const toSelectIndex = sCurveIds.indexOf(toSelectedId); // If we are already selecting the only selected s-curve, no reason to do anything if (toSelectIndex === firstSelectedIndex && toSelectIndex === lastSelectedIndex) return; // If toSelectedId doesn't represent a stored annotation, we can't do anything if (toSelectIndex === -1) return; if (toSelectIndex <= firstSelectedIndex) { const newSlice = sCurveIds.slice(toSelectIndex, firstSelectedIndex + 1); this.sCurveStore.selectSCurves([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } else { const newSlice = sCurveIds.slice(lastSelectedIndex, toSelectIndex + 1); this.sCurveStore.selectSCurves([...selectedIds.filter(id => !newSlice.includes(id)), ...newSlice]); } } setSCurveVisibility(ids, visible) { if (ids.length > 0) { this.sCurveStore.setSCurveVisibility(ids, visible); } } static ɵfac = function SCurveFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: SCurveFacade, factory: SCurveFacade.ɵfac }); } /***/ }, /***/ 82425 /*!***********************************************************!*\ !*** ./libs/store/src/lib/s-curve-store/s-curve.store.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurveStore: () => (/* binding */ sCurveStore) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var _ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngrx/signals/entities */ 13106); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../annotation-store/annotation.store */ 12973); function isStub(curve) { return curve?.type === 'stub'; } /** Spline s-curves and the stubs that stand in for them when unloaded - the two * shapes a spline annotation's own entity can currently be in this collection. */ function isStubOrSpline(curve) { if (isStub(curve)) return true; if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(curve)) return false; return (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsSpline)(curve); } /** Ids of relative measurements sourced from any of `sourceIds` - used to cascade * deletion when one or more of their source curves is removed. */ function getDependentMeasurementIds(entities, sourceIds) { const sourceIdSet = new Set(sourceIds); return entities.filter(entity => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)).filter(measurement => measurement.sourceIds.some(sourceId => sourceIdSet.has(sourceId))).map(({ id }) => id); } const initialState = { selectedIds: [] }; const sCurveStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.signalStore)((0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.withEntities)(), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withProps)(() => ({ annotationStore: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_6__.annotationStore) })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withComputed)(({ annotationStore }) => ({ splines: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => annotationStore.entities().filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsClosedSpline)(annotation)).map(spline => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.splineSCurve)(spline))) })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withComputed)(store => ({ relativeMeasurements: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => store.entities().filter(entity => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity))), sCurves: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => store.entities().filter(curve => !isStub(curve) && !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(curve))) })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withLinkedState)(({ sCurves, selectedIds }) => ({ selectedSCurves: () => { const ids = selectedIds(); const curves = sCurves(); return ids.map(id => curves.find(({ id: curveId }) => curveId === id)).filter(t => !!t); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withMethods)(({ annotationStore, ...store }) => ({ addRelativeMeasurement(measurement) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.addEntity)(measurement)); }, addSCurve(sCurve) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.addEntity)(sCurve)); }, /** * Deletes the given s-curves and/or relative measurements. Deleting a curve * also cascades to any relative measurement sourced from it, computed from a * single entities() snapshot and applied atomically so nothing ever observes a * measurement whose source was already removed. */ deleteSCurves(ids) { const requested = ids.map(id => store.entityMap()[id]).filter(entity => !!entity); if (requested.length === 0) { return; } const requestedCurveIds = requested.filter(entity => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)).map(({ id }) => id); const requestedMeasurementIds = requested.filter(entity => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)).map(({ id }) => id); const cascadedMeasurementIds = getDependentMeasurementIds(store.entities(), requestedCurveIds); const idsToDelete = [...new Set([...cascadedMeasurementIds, ...requestedCurveIds, ...requestedMeasurementIds])]; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, state => { return { selectedIds: state.selectedIds.filter(index => !idsToDelete.includes(index)), ...(0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.removeEntities)(idsToDelete)(state) }; }); }, /** * Returns true if the specified s-curve is one that is currently selected. * @param sCurve The s-curve to check * @returns Whether the s-curve is currently selected */ isSCurveSelected(sCurve) { return store.selectedIds().includes(sCurve.id); }, loadSCurves(sCurves) { const annotationCount = sCurves.length; const existing = store.entityMap(); const existingCount = Object.keys(existing).filter(id => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(existing[id])).length; // Don't need to replace an empty set with an empty set if (annotationCount === 0 && existingCount === 0) return; let replacements = 0; // If existing records are equal, keep those so references don't change for (const [index, sCurve] of sCurves.entries()) { const current = existing[sCurve.id]; if (current && (0,rxdb__WEBPACK_IMPORTED_MODULE_4__.deepEqual)(current, sCurve)) { sCurves[index] = current; replacements++; } } // If no actual changes, no need to continue if (annotationCount > 0 && replacements === annotationCount && (0,rxdb__WEBPACK_IMPORTED_MODULE_4__.deepEqual)(store.entities().filter(entity => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)).map(({ id }) => id), sCurves.map(({ id }) => id))) return; // Relative measurements aren't part of `sCurves` (loadSCurves is only ever // called with real curves), but they still live in this same entity // collection - preserve them across the full replace below. const measurements = store.entities().filter(entity => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.setAllEntities)([...sCurves, ...measurements])); }, /** * Reorders the relative measurements (e.g. after a drag-and-drop reorder in * the panel), preserving the current s-curves' order/position. */ reorderRelativeMeasurements(measurements) { const sCurves = store.entities().filter(entity => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.setAllEntities)([...sCurves, ...measurements])); }, /** * Stores the ids of which s-curves are "selected". * @param selectedIds The ids of s-curves to mark as selected. */ selectSCurves(selectedIds) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, { selectedIds }); }, /** * Sets the hidden status for a collection of s-curvevs. */ setSCurveVisibility(ids, visible) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.updateEntities)({ changes: { hidden: !visible }, ids })); }, /** * Updates an existing relative measurement's own fields (name/color/hidden - * sourceIds and the derived angle/position are never mutated directly). */ updateRelativeMeasurement(update) { const { id, ...changes } = update; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.updateEntity)({ changes, id })); }, /** * Updates an existing annotation in the collection * based on the fields received. * @param update A record containing the annotation id, and fields to change. */ updateSCurve(update) { const { id, ...changes } = update; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.updateEntity)({ changes, id })); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withMethods)(store => ({ // Curves/stubs only - relative measurements round-trip separately via // `relativeMeasurements()` / `reorderRelativeMeasurements()`, since they live in // this same entity collection but persist under their own schema field. export() { return store.entities().filter(curve => !(0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(curve)).map(curve => { if (!isStub(curve) && (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsSpline)(curve)) { return { hidden: curve.hidden, id: curve.id, type: 'stub' }; } return curve; }); }, import(curves) { const measurements = store.entities().filter(entity => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.sCurveIsRelativeMeasurement)(entity)); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.setAllEntities)([...curves, ...measurements])); } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.withHooks)({ onInit(store) { (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const { annotationStore, entities } = store; const splines = annotationStore.entities().filter(annotation => (0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.annotationIsClosedSpline)(annotation)); const existingSplineEntities = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(() => entities().filter(curve => isStubOrSpline(curve))); // Check any current spline s-curves / stubs - if any of these ids aren't in // `splines`, we can treat them as deletions. const storedSplineIds = existingSplineEntities.map(({ id }) => id); // TODO: Possibly filter out updates with no changes? const splineIds = new Set(splines.map(({ id }) => id)); const removedSplineIds = storedSplineIds.filter(id => !splineIds.has(id)); // A removed spline is the only way a SplineSCurve disappears outside // deleteSCurves() - cascade-delete any measurement sourced from it too, in // the same atomic update, so nothing ever observes a dangling source. const cascadedMeasurementIds = getDependentMeasurementIds((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.untracked)(entities), removedSplineIds); const updates = [...splines.map(spline => (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.setEntity)((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_5__.splineSCurve)(spline))), ...removedSplineIds.map(id => (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.removeEntity)(id)), ...cascadedMeasurementIds.map(id => (0,_ngrx_signals_entities__WEBPACK_IMPORTED_MODULE_3__.removeEntity)(id))]; if (updates.length > 0) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_2__.patchState)(store, ...updates); } }); } })); /***/ }, /***/ 40959 /*!************************************************************!*\ !*** ./libs/store/src/lib/services/measurement.service.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MeasurementService: () => (/* binding */ MeasurementService) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../annotation-store/annotation.store */ 12973); class MeasurementService { store = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_annotation_store_annotation_store__WEBPACK_IMPORTED_MODULE_4__.annotationStore); annotations = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.computeThrottled)(() => { return this.store.entityMap(); }, 100); _measurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)({}, ...(ngDevMode ? [{ debugName: "_measurements" }] : [])); // Store references to each annotation, so we can detect reference changes // and selectively update measurements lookup = new Map(); worker; constructor() { this.initWorker(); this.updateVolume(); } initWorker() { if (typeof Worker !== 'undefined') { this.worker = new Worker(__webpack_require__.tu(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("libs_store_src_lib_services_measurement_worker_ts"), __webpack_require__.b))); this.worker.addEventListener('message', ({ data }) => { if (data.type === 'annotation-measurements') { const current = this._measurements(); this._measurements.set({ ...current, ...data.measurements }); } }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const annotations = this.annotations(); const updates = {}; for (const [id, annotation] of Object.entries(annotations)) { if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_2__.annotationHasRelationship)(annotation)) { this.addSources(annotation, annotations, updates); } const existing = this.lookup.get(id); if (existing && existing === annotation) { continue; } updates[id] = annotation; this.lookup.set(id, annotation); } if (Object.keys(updates).length === 0) return; this.worker?.postMessage({ annotations: updates, type: 'generate-measurements' }); }); } } updateVolume(volumeId) { const volume = volumeId ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"].getVolume(volumeId) : (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.getPrimaryImageVolume)(); if (volume?.loadStatus?.['loaded'] === true) { const volumeData = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.exportFromImageVolume)(volume); if (volumeData) { this.worker?.postMessage({ type: 'set-volume', volume: volumeData }); } return; } setTimeout(() => this.updateVolume(volumeId), 100); } get annotationMeasurements() { return this._measurements.asReadonly(); } addSources(annotation, annotations, updates) { for (const sourceId of annotation.relationship.sourceIds) { const source = annotations[sourceId]; if (source && !(sourceId in updates)) { updates[sourceId] = source; } } } static ɵfac = function MeasurementService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MeasurementService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: MeasurementService, factory: MeasurementService.ɵfac }); } /***/ }, /***/ 75966 /*!**************************************************!*\ !*** ./libs/store/src/lib/ui-store/ui.facade.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ UiFacade: () => (/* binding */ UiFacade) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ui_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ui.store */ 80059); class UiFacade { store = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ui_store__WEBPACK_IMPORTED_MODULE_2__.uiStore); sCurveGraphDetached = this.store.sCurveGraph.detached; sCurveGraphPosition = this.store.sCurveGraph.position; sCurveGraphSize = this.store.sCurveGraph.size; sidebarSection = this.store.sidebar.openSection; sidebarOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.store.sidebar.openSection() !== undefined, ...(ngDevMode ? [{ debugName: "sidebarOpen" }] : [])); attachSCurveGraph() { this.store.attachSCurveGraph(); } detachSCurveGraph() { this.store.detachScurveGraph(); } moveSCurveGraph(position) { this.store.moveSCurveGraph(position); } resizeSCurveGraph(size) { this.store.resizeSCurveGraph(size); } closeSidebar() { this.store.closeSidebar(); } openSidebarSection(section) { this.store.openSidebarSection(section); } static ɵfac = function UiFacade_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UiFacade)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: UiFacade, factory: UiFacade.ɵfac }); } /***/ }, /***/ 80059 /*!*************************************************!*\ !*** ./libs/store/src/lib/ui-store/ui.store.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ uiStore: () => (/* binding */ uiStore) /* harmony export */ }); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngrx/signals */ 84102); function initialState() { return { sCurveGraph: { detached: false, position: { x: globalThis.window.innerWidth / 2, y: globalThis.window.innerHeight / 2 }, size: 320 }, sidebar: { openSection: undefined } }; } const uiStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withState)(initialState), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ attachSCurveGraph() { const existing = store.sCurveGraph(); if (existing.detached) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveGraph: { ...existing, detached: false } }); } }, closeSidebar() { if (store.sidebar.openSection() !== undefined) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sidebar: { openSection: undefined } }); } }, detachScurveGraph() { const existing = store.sCurveGraph(); if (!existing.detached) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveGraph: { ...existing, detached: true } }); } }, moveSCurveGraph(position) { const existing = store.sCurveGraph(); if (existing.position.x !== position.x && existing.position.y !== position.y) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveGraph: { ...existing, position } }); } }, openSidebarSection(openSection) { if (store.sidebar.openSection() !== openSection) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sidebar: { openSection } }); } }, resizeSCurveGraph(size) { const existing = store.sCurveGraph(); if (existing.size !== size) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { sCurveGraph: { ...existing, size } }); } } }))); /***/ }, /***/ 25144 /*!*************************************!*\ !*** ./libs/store/src/lib/utils.ts ***! \*************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ asUpdater: () => (/* binding */ asUpdater) /* harmony export */ }); function asUpdater( // eslint-disable-next-line @typescript-eslint/no-explicit-any updater) { return updater; } /***/ }, /***/ 96587 /*!*************************************************************!*\ !*** ./libs/store/src/lib/viewport-store/viewport.store.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ viewportStore: () => (/* binding */ viewportStore) /* harmony export */ }); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 85648); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); const INIT_VIEWPORT_MAPPINGS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.ALTERNATEBOTTOMLEFT]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.ALTERNATETOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.BOTTOMLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.MIDDLEMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.RIGHTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.TOPLEFTMAIN]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL }; function getAxis(matrix, column) { const start = AXIS_COLUMN[column] * 3; return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(matrix[start] ?? 0, matrix[start + 1] ?? 0, matrix[start + 2] ?? 0); } const AXIS_UP = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL }; // BLUE -> RED, RED -> GREEN, GREEN -> BLUE const AXIS_NEIGHBOUR = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL }; const AXIS_COLUMN = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: 2, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: 0, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: 1 }; // The `matrix` is the source of truth for the rotations of all viewports. // The `isocenter` is the point the camera looks at. To pan, you move it. // The `intersection` is the crosshair position / intersection of all planes. To scroll through slices, you move it. // The `cameraDistance` is the distance between the focalPoint and the camera. // If `isPosterior` is true, the matrix is flipped. // Initial `intersection` and `isocenter` will be overwritten with volume center const initialState = { ax: 0, cameraDistance: -10, crosshairSize: _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_CROSSHAIR_SIZE, intersection: [0.01, 0, 0], isocenter: [0, 0, 0], isPosterior: false, matrix: updateMatrix({ ax: 0, cc: 0, rl: 0 }, 0, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL), showCrosshairs: true, viewportAxisMapping: { ...INIT_VIEWPORT_MAPPINGS }, volumeCenter: undefined, zoom: 1 }; const viewportStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withState)(initialState), // Generate angulations (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ angulations: () => { return { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: angulations(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: angulations(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: angulations(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL) }; } })), // Generate crosshair rotation angles (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ crosshairRotations: () => { return { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: crosshairRotation(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: crosshairRotation(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: crosshairRotation(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL) }; } })), // Generate cornerstone camera details (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ cameras: () => { return { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL]: cameraDetails(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.AXIAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]: cameraDetails(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL]: cameraDetails(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.SAGITTAL) }; } })), // Generate viewport-aliased signals (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ primaryViewportAngulations: () => { const angulations = store.angulations(); const axisMapping = store.viewportAxisMapping(); return angulations[axisMapping[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.MIDDLEMAIN]]; }, viewportAngulations: () => { const out = {}; const angulations = store.angulations(); const axisMapping = store.viewportAxisMapping(); for (const viewport of Object.values(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState)) { out[viewport] = angulations[axisMapping[viewport]]; } return out; }, viewportCameras: () => { const out = {}; const cameras = store.cameras(); const axisMapping = store.viewportAxisMapping(); for (const viewport of Object.values(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState)) { out[viewport] = cameras[axisMapping[viewport]]; } return out; }, viewportCrosshairRotations: () => { const out = {}; const rotations = store.crosshairRotations(); const axisMapping = store.viewportAxisMapping(); for (const viewport of Object.values(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState)) { out[viewport] = rotations[axisMapping[viewport]]; } return out; } })), // Mutation methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ // Compute (but do not commit) the camera state cameraTargetForPosition(position, normal) { return computeCameraTarget(store, position, normal); }, nudgeAngulationsToForceResettle() { const { cc, rl } = store.primaryViewportAngulations(); requestAnimationFrame(() => { this.updateAngulations({ cc, rl: rl + 0.1 }); requestAnimationFrame(() => { this.updateAngulations({ cc, rl }); }); }); }, resetAngulations() { const isPosterior = false; const matrix = updateMatrix({ ax: 0, cc: 0, rl: 0 }, 0, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL); const viewportAxisMapping = { ...INIT_VIEWPORT_MAPPINGS }; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ax: 0, isPosterior, matrix, viewportAxisMapping }); }, resetCrosshairPosition() { const center = store.volumeCenter(); if (!center) return; const { intersection, isocenter } = keepIntersectionAndIsocenterDifferent({ intersection: center, isocenter: center }); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { intersection, isocenter }); }, resetState() { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ...initialState, viewportAxisMapping: { ...INIT_VIEWPORT_MAPPINGS } }); }, rotateAX(ax) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ax }); }, setCameraState(state) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, state); }, setCameraToPosition(position, normal) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, computeCameraTarget(store, position, normal)); }, // eslint-disable-next-line perfectionist/sort-objects rotateCrosshair(axis, degrees) { const original = store.matrix(); const normal = getAxis(original, axis); let rotation = crosshairRotation(store, axis); if (store.isPosterior()) { rotation = -rotation; degrees = -degrees; } // Keep the crosshair rotation within 180 const newRotation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(degrees - rotation); // Get the current CC/RL for this axis const angs = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vectorToAngulation)([normal[0], normal[1], normal[2]]); angs.ax = store.ax(); // Update the matrix with the new crosshair rotation + existing CC/RL for this axis const newMatrix = updateMatrix(angs, newRotation, axis); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { matrix: newMatrix }); }, setVolumeDetails(center) { const currentCenter = store.volumeCenter(); if (!currentCenter || !gl_matrix__WEBPACK_IMPORTED_MODULE_3__.equals(currentCenter, center)) { const angulation = store.angulations()[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL]; const rotation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(crosshairRotation(store, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL)); const matrix = updateMatrix(angulation, rotation, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxis.CORONAL); const { intersection, isocenter } = keepIntersectionAndIsocenterDifferent({ intersection: center, isocenter: center }); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { intersection, isocenter, matrix, volumeCenter: center }); } }, swapViewportAxis(from) { if (from === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.MIDDLEMAIN) return; const original = store.matrix(); const axial = original.slice(0, 3); const sagittal = original.slice(3, 6); const coronal = original.slice(6, 9); const newMatrix = from === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.TOPLEFTMAIN ? gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(...coronal, ...sagittal, ...axial) : gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(...sagittal, ...axial, ...coronal); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { matrix: newMatrix }); }, updateAngulations(angulation) { const activeAxis = store.viewportAxisMapping()[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.MIDDLEMAIN]; const current = store.angulations()[activeAxis]; const updated = { ...current, ...angulation }; let rotation = -(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(crosshairRotation(store, activeAxis)); if (store.isPosterior()) { rotation = -rotation; } const newMatrix = updateMatrix(updated, rotation, activeAxis); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { matrix: newMatrix }); }, updateAngulationsForAllAxes(blue, red, green) { const [blueVec, redVec, greenVec] = [ang2vec(blue), ang2vec(red), ang2vec(green)]; const newMatrix = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(blueVec[0], blueVec[1], blueVec[2], redVec[0], redVec[1], redVec[2], greenVec[0], greenVec[1], greenVec[2]); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { matrix: newMatrix }); }, updateAngulationsForAxis(angulation, axis) { const current = store.angulations()[axis]; const updated = { ...current, ...angulation }; let rotation = -(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(crosshairRotation(store, axis)); if (store.isPosterior()) { rotation = -rotation; } const newMatrix = updateMatrix(updated, rotation, axis); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { matrix: newMatrix }); }, updateCrosshairSize(crosshairSize) { if (crosshairSize !== store.crosshairSize()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { crosshairSize }); } }, updateCrosshairVisibility(showCrosshairs) { if (showCrosshairs !== store.showCrosshairs()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { showCrosshairs }); } }, // Use to move crosshair pos updateIntersection(newIntersection) { const { intersection } = keepIntersectionAndIsocenterDifferent({ intersection: newIntersection, isocenter: store.isocenter() }); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { intersection }); }, // Move to pan camera updateIsoCenter(isocenter) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { isocenter }); }, updatePosterior(isPosterior) { if (isPosterior !== store.isPosterior()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { isPosterior }); } }, updateZoom(zoom) { if (zoom !== store.zoom()) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { zoom }); } } })), // State management methods (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withMethods)(store => ({ import(state) { // If no volume center has been set, this was likely an // initial import and we don't want to overwrite the // upcoming `setVolumeDetails()` call if (state.volumeCenter === undefined) { delete state.intersection; delete state.isocenter; delete state.volumeCenter; } if (state.volumeCenter !== undefined && state.intersection !== undefined && state.isocenter !== undefined) { const guarded = keepIntersectionAndIsocenterDifferent({ intersection: state.intersection, isocenter: state.isocenter }); state = { ...state, ...guarded }; } if (Object.keys(state).length > 0) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.patchState)(store, { ...state }); } } })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_0__.withLinkedState)(store => ({ export: () => ({ ax: store.ax(), cameraDistance: store.cameraDistance(), intersection: store.intersection(), isocenter: store.isocenter(), isPosterior: store.isPosterior(), matrix: store.matrix(), showCrosshairs: store.showCrosshairs(), viewportAxisMapping: store.viewportAxisMapping(), volumeCenter: store.volumeCenter(), zoom: store.zoom() }) }))); function computeCameraTarget(store, position, normal) { const activeAxis = store.viewportAxisMapping()[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.ViewportAxisState.MIDDLEMAIN]; const nextState = keepIntersectionAndIsocenterDifferent({ intersection: position, isocenter: position }); if (normal) { const angulation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vectorToAngulation)(normal); let rotation = -(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(crosshairRotation(store, activeAxis)); if (store.isPosterior()) { rotation = -rotation; } nextState.matrix = updateMatrix(angulation, rotation, activeAxis); } return nextState; } function keepIntersectionAndIsocenterDifferent(state) { return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.equals(state.intersection, state.isocenter) ? { intersection: [state.intersection[0] + 0.01, state.intersection[1], state.intersection[2]], isocenter: state.isocenter } : { intersection: state.intersection, isocenter: state.isocenter }; } /** * Using the stored intersection, isocenter and transformation matrix, * returns Cornerstone camera configuration for the requested viewport axis. */ function cameraDetails(store, normalAxis) { const focalPoint = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(...store.isocenter()); let { viewPlaneNormal } = getNormals(store, normalAxis); viewPlaneNormal = flippedNormal(viewPlaneNormal); const angulation = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vectorToAngulation)([viewPlaneNormal[0], viewPlaneNormal[1], viewPlaneNormal[2]]); const { up: viewUp } = basisVectors(viewPlaneNormal, angulation.cc, angulation.rl, store.ax()); const q = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(); // Show posterior view by rotating camera 180, so that // we don't need to account for it in the matrix/sliders if (store.isPosterior()) { gl_matrix__WEBPACK_IMPORTED_MODULE_2__.setAxisAngle(q, viewUp, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(180)); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.transformQuat(viewPlaneNormal, viewPlaneNormal, q); } const cameraDistance = store.cameraDistance(); // Compute the camera position by moving back from the focalPoint along the normal const position = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scaleAndAdd(position, focalPoint, viewPlaneNormal, cameraDistance); // Ensure the focalPoint is aligned to the same depth as the crosshair const intersection = store.intersection(); const distance = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.subtract(distance, intersection, focalPoint); const shift = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dot(distance, viewPlaneNormal); const shiftedNormal = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(shiftedNormal, viewPlaneNormal, shift); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.add(focalPoint, focalPoint, shiftedNormal); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.add(position, position, shiftedNormal); return { focalPoint, position, viewPlaneNormal, viewUp }; } function crosshairRotation(store, normalAxis) { const matrix = store.matrix(); const isPosterior = store.isPosterior(); let normal = getAxis(matrix, normalAxis); let neighbourNormal = getAxis(matrix, AXIS_NEIGHBOUR[normalAxis]); normal = flippedNormal(normal); neighbourNormal = flippedNormal(neighbourNormal); const angulation = vec2angle(normal); const { right: viewRight, up: viewUp } = basisVectors(normal, angulation.cc, angulation.rl, store.ax()); const angle = crosshairAngle(viewRight, viewUp, neighbourNormal); return isPosterior ? angle : -angle; } function crosshairAngle(rightVector, upVector, neighbourNormal) { const xScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dot(neighbourNormal, rightVector); const yScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.dot(neighbourNormal, upVector); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.rad2deg)(Math.atan2(yScreen, xScreen)); } function angulations(store, axis) { const matrix = store.matrix(); const ax = store.ax(); const viewPlaneNormal = getAxis(matrix, axis); const { cc, rl } = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.vectorToAngulation)((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.position)(viewPlaneNormal[0], viewPlaneNormal[1], viewPlaneNormal[2])); return { ax, cc, rl }; } function vec2angle(vector) { const cc = -Math.asin(vector[2]) / Math.PI * 180; const rl = -Math.atan2(vector[0], vector[1]) / Math.PI * 180; return { ax: 0, cc, rl }; } function getNormals(store, axis) { const matrix = store.matrix(); const viewPlaneNormal = getAxis(matrix, axis); const viewUp = getAxis(matrix, AXIS_UP[axis]); return { viewPlaneNormal, viewUp }; } function ang2vec({ cc, rl }) { cc = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(cc); rl = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(rl); const vec = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(-Math.sin(rl) * Math.cos(cc), Math.cos(rl) * Math.cos(cc), -Math.sin(cc)); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(vec, vec); return vec; } /** * Calculates the up/right vectors for a given view normal. * @param normal The normal to generate basis vectors for * @param rl The current RL angle for the normal (in degrees) * @returns Up/Right vectors for a given view normal */ function basisVectors(normal, cc, rl, ax) { rl = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(rl); ax = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(ax); cc = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.deg2rad)(cc); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(normal, normal); const up = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(-(Math.cos(rl) * Math.sin(ax)) - Math.sin(rl) * Math.sin(cc) * Math.cos(ax), -(Math.sin(rl) * Math.sin(ax)) + Math.cos(rl) * Math.sin(cc) * Math.cos(ax), Math.cos(cc) * Math.cos(ax)); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(up, up); const right = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), normal, up); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(right, right); return { angleNormal: normal, right, up }; } function updateMatrix(angulation, blueCrosshair, blueAxis) { const newMatrix = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); const blueTest = ang2vec(angulation); const { angleNormal: blue, right, up } = basisVectors(blueTest, angulation.cc, angulation.rl, angulation.ax); const red = redVector(blueCrosshair, right, up); const green = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.cross(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), blue, red); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(blue, blue); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(red, red); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(green, green); // Columns are are always ordered blue/red/green, // though they can wrap to the beginning of the matrix // if not starting at 0. const blueColumn = AXIS_COLUMN[blueAxis] * 3; const redColumn = (AXIS_COLUMN[blueAxis] + 1) % 3 * 3; const greenColumn = (AXIS_COLUMN[blueAxis] + 2) % 3 * 3; newMatrix[blueColumn] = blue[0]; newMatrix[blueColumn + 1] = blue[1]; newMatrix[blueColumn + 2] = blue[2]; newMatrix[redColumn] = red[0]; newMatrix[redColumn + 1] = red[1]; newMatrix[redColumn + 2] = red[2]; newMatrix[greenColumn] = green[0]; newMatrix[greenColumn + 1] = green[1]; newMatrix[greenColumn + 2] = green[2]; return newMatrix; } function redVector(blueCrosshair, right, up) { const a = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), right, Math.cos(blueCrosshair)); const b = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), up, Math.sin(blueCrosshair)); return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), a, b); } // Ensures the normal is flipped when necessary to stay within // the desired camera range function flippedNormal(normal) { if (normal[1] < 0) return gl_matrix__WEBPACK_IMPORTED_MODULE_3__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_3__.create(), normal, -1); return normal; } /***/ }, /***/ 51217 /*!*****************************************************************!*\ !*** ./libs/store/src/lib/volume-viewer/volume-viewer.store.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ volumeViewerStore: () => (/* binding */ volumeViewerStore) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngrx_signals__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngrx/signals */ 84102); /* harmony import */ var rxdb__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxdb */ 99984); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _render_settings_store_render_settings_store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../render-settings-store/render-settings.store */ 58029); // TODO: Remove this store entirely - migrate the necessary `loadSeries()` logic elsewhere const volumeViewerStore = (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.signalStore)((0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.withState)({ imageIdsError: undefined, phaseSelection: {}, registeredViewports: {}, requestedActiveVolume: undefined, seriesPhases: {}, seriesWindow: {}, status: 'idle' }), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.withComputed)(({ registeredViewports }) => ({ viewportStates: (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => Object.values(registeredViewports())) })), (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.withMethods)(store => { const loader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_5__.VolumeLoaderService); // Temp const renderSettings = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_render_settings_store_render_settings_store__WEBPACK_IMPORTED_MODULE_8__.renderSettingsStore); const getSeriesWindow = seriesUid => { return store.seriesWindow()[seriesUid]; }; const getSeriesPhases = seriesUid => { return store.seriesPhases()[seriesUid] ?? []; }; const getPhaseSelection = seriesUid => { return store.phaseSelection()[seriesUid]; }; return { deregisterViewport(viewportId) { const current = store.registeredViewports(); const viewport = current[viewportId]; if (!viewport) return; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { registeredViewports: { ...current, [viewportId]: { ...viewport, element: undefined, isInitialized: false } } }); }, loadSeries(studyUid, seriesUid, storeUid, selectedPhaseIds) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { imageIdsError: undefined, status: 'loading' }); try { yield loader.init(); const phases = yield loader.ensureSeriesPhases(studyUid, seriesUid, storeUid, selectedPhaseIds); (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, state => ({ seriesPhases: { ...state.seriesPhases, [seriesUid]: phases } })); // The active phase's volume is built lazily by the viewer; the series-level window is // derived from the first phase (all phases share acquisition geometry). const imageIds = phases[0]?.imageIds ?? []; const windowMetadata = imageIds.length > 0 ? loader.getWindowMetadata(imageIds) : undefined; if (!windowMetadata) return imageIds; const seriesWindow = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.buildSeriesWindowState)(windowMetadata, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_WINDOW_PRESET, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_MAX_PIXELS); // TODO: Move loading outside of signal store if (renderSettings.windowPresets().length === 0) { renderSettings.setWindowPresets(seriesWindow.windowPresets); } // MIP just displays the projected image windowed like any other CT image // (threshold/brightness = window width/level - see MipSettings), so it should start // from the same DICOM-derived window this series' MPR views use, not the generic // static preset default. const volumeRenderingPresets = Object.values(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.VOLUME_RENDERING_PRESETS).map(preset => preset.selectedPreset === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.VolumeRenderingOption.MIP ? { ...preset, brightness: seriesWindow.defaultWindowLevel, threshold: seriesWindow.defaultWindowWidth } : preset); if (renderSettings.volumeRenderPresets().length === 0) { renderSettings.setVolumePresets(volumeRenderingPresets); } else { renderSettings.addMissingVolumePresets(volumeRenderingPresets); } (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, state => ({ registeredViewports: Object.fromEntries(Object.entries(state.registeredViewports).map(([id, viewport]) => [id, (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.getDefaultViewport)(viewport)])), seriesWindow: { ...state.seriesWindow, [seriesUid]: seriesWindow } })); return imageIds; } catch (error) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { imageIdsError: error, status: 'error' }); throw error; } })(); }, markViewportsInitialized(viewportIds) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, state => { const next = { ...state.registeredViewports }; for (const id of viewportIds) { const viewport = next[id]; if (viewport) next[id] = { ...viewport, isInitialized: true }; } return { registeredViewports: next }; }); }, phaseSelectionState(seriesUid) { return getPhaseSelection(seriesUid); }, registerViewport(element, options, _seriesUid) { const current = store.registeredViewports(); const existing = current[options.id]; if (existing && existing.element === element) return; const baseConfig = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_7__.getDefaultViewport)(options); const inheritedValues = {}; const viewportState = { ...baseConfig, ...options, ...inheritedValues, element, isInitialized: false }; if ((0,rxdb__WEBPACK_IMPORTED_MODULE_4__.deepEqual)(existing, viewportState)) return; (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { registeredViewports: { ...current, [options.id]: viewportState } }); }, requestActiveVolume(request) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, request ? { requestedActiveVolume: { phaseId: request.phaseId, revealAnnotationId: request.revealAnnotationId ?? undefined, revealChamberId: request.revealChamberId ?? undefined } } : { requestedActiveVolume: request }); }, resetForSeriesChange() { // phaseSelection is intentionally NOT cleared: a restored work-session selection must // survive the series reset that precedes opening the series. (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, state => ({ imageIdsError: undefined, registeredViewports: Object.fromEntries(Object.entries(state.registeredViewports).map(([id, viewport]) => [id, { ...viewport, isInitialized: false }])), requestedActiveVolume: undefined, seriesPhases: {}, seriesWindow: {}, status: 'idle' })); }, seriesPhasesState(seriesUid) { return getSeriesPhases(seriesUid); }, seriesWindowState(seriesUid) { return getSeriesWindow(seriesUid); }, setImageIdsError(error) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { imageIdsError: error }); }, setPhaseSelection(seriesUid, selection) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, state => ({ phaseSelection: { ...state.phaseSelection, [seriesUid]: selection } })); }, setStatus(status) { (0,_ngrx_signals__WEBPACK_IMPORTED_MODULE_3__.patchState)(store, { status }); }, wasSeriesUnseparable(studyUid, seriesUid, storeUid) { return loader.wasSeriesUnseparable(studyUid, seriesUid, storeUid); } }; })); /***/ }, /***/ 60450 /*!******************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/angle.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ angle: () => (/* binding */ angle) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums_annotation_source_type_enum__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums/annotation-source-type.enum */ 31935); function angle(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums_annotation_source_type_enum__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.ANGLE, ...data }; } /***/ }, /***/ 60807 /*!**************************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/closed-spline.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closedSpline: () => (/* binding */ closedSpline) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function closedSpline(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CLOSED_SPLINE, ...data }; } /***/ }, /***/ 63231 /*!*********************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/cylinder.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cylinder: () => (/* binding */ cylinder) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function cylinder(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.CYLINDER, ...data }; } /***/ }, /***/ 21994 /*!*********************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/distance.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ distance: () => (/* binding */ distance) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function distance(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.DISTANCE, ...data }; } /***/ }, /***/ 67541 /*!****************************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/hollow-cylinder.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ hollowCylinder: () => (/* binding */ hollowCylinder) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function hollowCylinder(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.HOLLOW_CYLINDER, ...data }; } /***/ }, /***/ 84837 /*!******************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/index.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ angle: () => (/* reexport safe */ _angle__WEBPACK_IMPORTED_MODULE_0__.angle), /* harmony export */ annotationHasPoints: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationHasPoints), /* harmony export */ annotationHasPosition: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationHasPosition), /* harmony export */ annotationHasRelationship: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationHasRelationship), /* harmony export */ annotationIsAngle: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsAngle), /* harmony export */ annotationIsClosedSpline: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsClosedSpline), /* harmony export */ annotationIsCylinder: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsCylinder), /* harmony export */ annotationIsDistance: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsDistance), /* harmony export */ annotationIsHollowCylinder: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsHollowCylinder), /* harmony export */ annotationIsObject3D: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsObject3D), /* harmony export */ annotationIsOpenSpline: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsOpenSpline), /* harmony export */ annotationIsPoint: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsPoint), /* harmony export */ annotationIsSpline: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsSpline), /* harmony export */ annotationIsStl: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_8__.annotationIsStl), /* harmony export */ closedSpline: () => (/* reexport safe */ _closed_spline__WEBPACK_IMPORTED_MODULE_1__.closedSpline), /* harmony export */ cylinder: () => (/* reexport safe */ _cylinder__WEBPACK_IMPORTED_MODULE_2__.cylinder), /* harmony export */ distance: () => (/* reexport safe */ _distance__WEBPACK_IMPORTED_MODULE_3__.distance), /* harmony export */ hollowCylinder: () => (/* reexport safe */ _hollow_cylinder__WEBPACK_IMPORTED_MODULE_4__.hollowCylinder), /* harmony export */ openSpline: () => (/* reexport safe */ _open_spline__WEBPACK_IMPORTED_MODULE_5__.openSpline), /* harmony export */ point: () => (/* reexport safe */ _point__WEBPACK_IMPORTED_MODULE_6__.point), /* harmony export */ stlObject3D: () => (/* reexport safe */ _stl_object3d__WEBPACK_IMPORTED_MODULE_7__.stlObject3D) /* harmony export */ }); /* harmony import */ var _angle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./angle */ 60450); /* harmony import */ var _closed_spline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./closed-spline */ 60807); /* harmony import */ var _cylinder__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./cylinder */ 63231); /* harmony import */ var _distance__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./distance */ 21994); /* harmony import */ var _hollow_cylinder__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hollow-cylinder */ 67541); /* harmony import */ var _open_spline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./open-spline */ 30671); /* harmony import */ var _point__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./point */ 94759); /* harmony import */ var _stl_object3d__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./stl-object3d */ 8261); /* harmony import */ var _type_checks__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./type-checks */ 22599); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./types */ 87744); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_types__WEBPACK_IMPORTED_MODULE_9__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_9__) if(["default","angle","closedSpline","cylinder","distance","hollowCylinder","openSpline","point","stlObject3D","annotationHasPoints","annotationHasPosition","annotationHasRelationship","annotationIsAngle","annotationIsClosedSpline","annotationIsCylinder","annotationIsDistance","annotationIsHollowCylinder","annotationIsObject3D","annotationIsOpenSpline","annotationIsPoint","annotationIsSpline","annotationIsStl"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _types__WEBPACK_IMPORTED_MODULE_9__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /***/ }, /***/ 30671 /*!************************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/open-spline.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ openSpline: () => (/* binding */ openSpline) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function openSpline(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.OPEN_SPLINE, ...data }; } /***/ }, /***/ 94759 /*!******************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/point.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ point: () => (/* binding */ point) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function point(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.POINT, ...data }; } /***/ }, /***/ 8261 /*!*************************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/stl-object3d.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ stlObject3D: () => (/* binding */ stlObject3D) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../enums */ 66556); function stlObject3D(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: _enums__WEBPACK_IMPORTED_MODULE_1__.AnnotationSourceType.STL, ...data }; } /***/ }, /***/ 22599 /*!************************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/type-checks.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationHasPoints: () => (/* binding */ annotationHasPoints), /* harmony export */ annotationHasPosition: () => (/* binding */ annotationHasPosition), /* harmony export */ annotationHasRelationship: () => (/* binding */ annotationHasRelationship), /* harmony export */ annotationIsAngle: () => (/* binding */ annotationIsAngle), /* harmony export */ annotationIsClosedSpline: () => (/* binding */ annotationIsClosedSpline), /* harmony export */ annotationIsCylinder: () => (/* binding */ annotationIsCylinder), /* harmony export */ annotationIsDistance: () => (/* binding */ annotationIsDistance), /* harmony export */ annotationIsHollowCylinder: () => (/* binding */ annotationIsHollowCylinder), /* harmony export */ annotationIsObject3D: () => (/* binding */ annotationIsObject3D), /* harmony export */ annotationIsOpenSpline: () => (/* binding */ annotationIsOpenSpline), /* harmony export */ annotationIsPoint: () => (/* binding */ annotationIsPoint), /* harmony export */ annotationIsSpline: () => (/* binding */ annotationIsSpline), /* harmony export */ annotationIsStl: () => (/* binding */ annotationIsStl) /* harmony export */ }); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../enums */ 66556); function annotationHasPoints(annotation) { return !!annotation && 'points' in annotation; } function annotationHasPosition(annotation) { return !!annotation && 'position' in annotation; } function annotationHasRelationship(annotation) { return !!annotation && 'relationship' in annotation && annotation.relationship !== undefined; } function annotationIsAngle(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE; } function annotationIsDistance(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE; } function annotationIsPoint(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT; } function annotationIsSpline(annotation) { return !!annotation && [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE].includes(annotation.type); } function annotationIsClosedSpline(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE; } function annotationIsOpenSpline(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE; } function annotationIsObject3D(annotation) { return !!annotation && [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CYLINDER, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.HOLLOW_CYLINDER, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.STL].includes(annotation.type); } function annotationIsCylinder(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CYLINDER; } function annotationIsHollowCylinder(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.HOLLOW_CYLINDER; } function annotationIsStl(annotation) { return annotation?.type === _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.STL; } /***/ }, /***/ 87744 /*!******************************************************!*\ !*** ./libs/types/src/lib/dtos/annotations/types.ts ***! \******************************************************/ () { /***/ }, /***/ 31809 /*!**********************************************************!*\ !*** ./libs/types/src/lib/dtos/chamber/chamber-group.ts ***! \**********************************************************/ () { /***/ }, /***/ 83553 /*!**************************************************!*\ !*** ./libs/types/src/lib/dtos/chamber/index.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./types */ 98804); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_types__WEBPACK_IMPORTED_MODULE_0__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _types__WEBPACK_IMPORTED_MODULE_0__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _chamber_group__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chamber-group */ 31809); /* harmony import */ var _chamber_group__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_chamber_group__WEBPACK_IMPORTED_MODULE_1__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _chamber_group__WEBPACK_IMPORTED_MODULE_1__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _chamber_group__WEBPACK_IMPORTED_MODULE_1__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /***/ }, /***/ 98804 /*!**************************************************!*\ !*** ./libs/types/src/lib/dtos/chamber/types.ts ***! \**************************************************/ () { /***/ }, /***/ 85549 /*!*******************************************************!*\ !*** ./libs/types/src/lib/dtos/dicom-study-search.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MODALITY_OPTIONS: () => (/* binding */ MODALITY_OPTIONS), /* harmony export */ reviewStatusRank: () => (/* binding */ reviewStatusRank) /* harmony export */ }); const MODALITY_OPTIONS = ['CT', 'MR', 'XA', 'US', 'PT', 'CR', 'NM', 'OT']; const REVIEW_STATUS_RANK = { approved: 3, none: 0, rejected: 2, unapproved: 1 }; /** Numeric precedence for sorting: approved (3) > rejected (2) > unapproved (1) > none (0). */ function reviewStatusRank(status) { return REVIEW_STATUS_RANK[status]; } /***/ }, /***/ 55492 /*!******************************************!*\ !*** ./libs/types/src/lib/dtos/index.ts ***! \******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEFAULT_S_CURVE_GRAPH_FONT_SIZE: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE), /* harmony export */ DEFAULT_S_CURVE_LINE_WIDTH: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_S_CURVE_LINE_WIDTH), /* harmony export */ MODALITY_OPTIONS: () => (/* reexport safe */ _dicom_study_search__WEBPACK_IMPORTED_MODULE_4__.MODALITY_OPTIONS), /* harmony export */ TVCT_LEGACY_MANUFACTURER: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.TVCT_LEGACY_MANUFACTURER), /* harmony export */ TVCT_PRIVATE_CREATOR: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.TVCT_PRIVATE_CREATOR), /* harmony export */ TVCT_WORK_SESSION_DESCRIPTION_PREFIX: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.TVCT_WORK_SESSION_DESCRIPTION_PREFIX), /* harmony export */ TVCT_WORK_SESSION_TYPE: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.TVCT_WORK_SESSION_TYPE), /* harmony export */ controlPointSCurve: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.controlPointSCurve), /* harmony export */ isTvctWorkSessionInstance: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.isTvctWorkSessionInstance), /* harmony export */ isTvctWorkSessionSeries: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.isTvctWorkSessionSeries), /* harmony export */ reviewStatusRank: () => (/* reexport safe */ _dicom_study_search__WEBPACK_IMPORTED_MODULE_4__.reviewStatusRank), /* harmony export */ sCurveAngleMeasurement: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveAngleMeasurement), /* harmony export */ sCurveIntersectionMeasurement: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveIntersectionMeasurement), /* harmony export */ sCurveIsControlPoint: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveIsControlPoint), /* harmony export */ sCurveIsRelativeMeasurement: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveIsRelativeMeasurement), /* harmony export */ sCurveIsSpline: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveIsSpline), /* harmony export */ sCurveIsStub: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveIsStub), /* harmony export */ sCurveMeasurementIsAngle: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveMeasurementIsAngle), /* harmony export */ sCurveMeasurementIsIntersection: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.sCurveMeasurementIsIntersection), /* harmony export */ splineSCurve: () => (/* reexport safe */ _s_curves__WEBPACK_IMPORTED_MODULE_3__.splineSCurve), /* harmony export */ toTvctWorkSessionDescription: () => (/* reexport safe */ _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__.toTvctWorkSessionDescription) /* harmony export */ }); /* harmony import */ var _relationships__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./relationships */ 47516); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _relationships__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _relationships__WEBPACK_IMPORTED_MODULE_0__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _protocols__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./protocols */ 24490); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _protocols__WEBPACK_IMPORTED_MODULE_1__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _protocols__WEBPACK_IMPORTED_MODULE_1__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _annotations__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotations */ 84837); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _annotations__WEBPACK_IMPORTED_MODULE_2__) if(["default","RELATIONSHIP_SPECS","LEGACY_TAVI_PROTOCOL_IDS","TAVI_PROTOCOL_ID","canonicalProtocolId","isTaviProtocolId","placeholder","placeholderHasRelationship","protocolInstance"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _annotations__WEBPACK_IMPORTED_MODULE_2__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _s_curves__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./s-curves */ 49089); /* harmony import */ var _dicom_study_search__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./dicom-study-search */ 85549); /* harmony import */ var _tvct_work_session__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./tvct-work-session */ 38504); /* harmony import */ var _chamber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./chamber */ 83553); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _chamber__WEBPACK_IMPORTED_MODULE_6__) if(["default","RELATIONSHIP_SPECS","LEGACY_TAVI_PROTOCOL_IDS","TAVI_PROTOCOL_ID","canonicalProtocolId","isTaviProtocolId","placeholder","placeholderHasRelationship","protocolInstance","angle","annotationHasPoints","annotationHasPosition","annotationHasRelationship","annotationIsAngle","annotationIsClosedSpline","annotationIsCylinder","annotationIsDistance","annotationIsHollowCylinder","annotationIsObject3D","annotationIsOpenSpline","annotationIsPoint","annotationIsSpline","annotationIsStl","closedSpline","cylinder","distance","hollowCylinder","openSpline","point","stlObject3D","DEFAULT_S_CURVE_GRAPH_FONT_SIZE","DEFAULT_S_CURVE_LINE_WIDTH","controlPointSCurve","sCurveAngleMeasurement","sCurveIntersectionMeasurement","sCurveIsControlPoint","sCurveIsRelativeMeasurement","sCurveIsSpline","sCurveIsStub","sCurveMeasurementIsAngle","sCurveMeasurementIsIntersection","splineSCurve","MODALITY_OPTIONS","reviewStatusRank","TVCT_LEGACY_MANUFACTURER","TVCT_PRIVATE_CREATOR","TVCT_WORK_SESSION_DESCRIPTION_PREFIX","TVCT_WORK_SESSION_TYPE","isTvctWorkSessionInstance","isTvctWorkSessionSeries","toTvctWorkSessionDescription"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _chamber__WEBPACK_IMPORTED_MODULE_6__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); // ENUMS /***/ }, /***/ 51169 /*!**********************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/field-definitions.ts ***! \**********************************************************************/ () { /***/ }, /***/ 80794 /*!********************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/form-definition.ts ***! \********************************************************************/ () { /***/ }, /***/ 55582 /*!**********************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/index.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ and: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.and), /* harmony export */ equals: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.equals), /* harmony export */ fail: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.fail), /* harmony export */ forField: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.forField), /* harmony export */ iff: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.iff), /* harmony export */ isFail: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.isFail), /* harmony export */ isPass: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.isPass), /* harmony export */ isSkip: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.isSkip), /* harmony export */ oneOf: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.oneOf), /* harmony export */ or: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.or), /* harmony export */ pass: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.pass), /* harmony export */ required: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.required), /* harmony export */ skip: () => (/* reexport safe */ _validation__WEBPACK_IMPORTED_MODULE_2__.skip) /* harmony export */ }); /* harmony import */ var _form_definition__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./form-definition */ 80794); /* harmony import */ var _form_definition__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_form_definition__WEBPACK_IMPORTED_MODULE_0__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _form_definition__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _form_definition__WEBPACK_IMPORTED_MODULE_0__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _field_definitions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./field-definitions */ 51169); /* harmony import */ var _field_definitions__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_field_definitions__WEBPACK_IMPORTED_MODULE_1__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _field_definitions__WEBPACK_IMPORTED_MODULE_1__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _field_definitions__WEBPACK_IMPORTED_MODULE_1__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _validation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./validation */ 38024); /***/ }, /***/ 48230 /*!***************************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/validation/field-rules.ts ***! \***************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ and: () => (/* binding */ and), /* harmony export */ equals: () => (/* binding */ equals), /* harmony export */ forField: () => (/* binding */ forField), /* harmony export */ iff: () => (/* binding */ iff), /* harmony export */ oneOf: () => (/* binding */ oneOf), /* harmony export */ or: () => (/* binding */ or), /* harmony export */ required: () => (/* binding */ required) /* harmony export */ }); function and(...rules) { return { rules, type: 'and' }; } function iff(condition, rule, elseRule) { return { condition, elseRule, rule, type: 'if' }; } function equals(value, message) { return { message, type: 'equals', value }; } function forField(field, rule) { return { field, rule, type: 'for-field' }; } function oneOf(values, message) { return { message, type: 'one-of', values }; } function or(...rules) { return { rules, type: 'or' }; } function required(message) { return { message, type: 'required' }; } /***/ }, /***/ 38024 /*!*********************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/validation/index.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ and: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.and), /* harmony export */ equals: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.equals), /* harmony export */ fail: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.fail), /* harmony export */ forField: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.forField), /* harmony export */ iff: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.iff), /* harmony export */ isFail: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.isFail), /* harmony export */ isPass: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.isPass), /* harmony export */ isSkip: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.isSkip), /* harmony export */ oneOf: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.oneOf), /* harmony export */ or: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.or), /* harmony export */ pass: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.pass), /* harmony export */ required: () => (/* reexport safe */ _field_rules__WEBPACK_IMPORTED_MODULE_0__.required), /* harmony export */ skip: () => (/* reexport safe */ _result__WEBPACK_IMPORTED_MODULE_1__.skip) /* harmony export */ }); /* harmony import */ var _field_rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./field-rules */ 48230); /* harmony import */ var _result__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./result */ 42347); /***/ }, /***/ 42347 /*!**********************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/forms/validation/result.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ fail: () => (/* binding */ fail), /* harmony export */ isFail: () => (/* binding */ isFail), /* harmony export */ isPass: () => (/* binding */ isPass), /* harmony export */ isSkip: () => (/* binding */ isSkip), /* harmony export */ pass: () => (/* binding */ pass), /* harmony export */ skip: () => (/* binding */ skip) /* harmony export */ }); const PASS_ = { result: 'pass' }; function pass() { return PASS_; } const SKIP_ = { result: 'skip' }; function skip() { return SKIP_; } function fail(error) { return { error, result: 'fail' }; } function isPass(result) { return result.result === 'pass'; } function isFail(result) { return result.result === 'fail'; } function isSkip(result) { return result.result === 'skip'; } /***/ }, /***/ 24490 /*!****************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/index.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LEGACY_TAVI_PROTOCOL_IDS: () => (/* reexport safe */ _protocol_ids__WEBPACK_IMPORTED_MODULE_3__.LEGACY_TAVI_PROTOCOL_IDS), /* harmony export */ TAVI_PROTOCOL_ID: () => (/* reexport safe */ _protocol_ids__WEBPACK_IMPORTED_MODULE_3__.TAVI_PROTOCOL_ID), /* harmony export */ canonicalProtocolId: () => (/* reexport safe */ _protocol_ids__WEBPACK_IMPORTED_MODULE_3__.canonicalProtocolId), /* harmony export */ isTaviProtocolId: () => (/* reexport safe */ _protocol_ids__WEBPACK_IMPORTED_MODULE_3__.isTaviProtocolId), /* harmony export */ placeholder: () => (/* reexport safe */ _placeholder__WEBPACK_IMPORTED_MODULE_1__.placeholder), /* harmony export */ placeholderHasRelationship: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_5__.placeholderHasRelationship), /* harmony export */ protocolInstance: () => (/* reexport safe */ _protocol_instance__WEBPACK_IMPORTED_MODULE_4__.protocolInstance) /* harmony export */ }); /* harmony import */ var _forms__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./forms */ 55582); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _forms__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _forms__WEBPACK_IMPORTED_MODULE_0__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _placeholder__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./placeholder */ 43403); /* harmony import */ var _protocol_definition__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./protocol-definition */ 35816); /* harmony import */ var _protocol_definition__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_protocol_definition__WEBPACK_IMPORTED_MODULE_2__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _protocol_definition__WEBPACK_IMPORTED_MODULE_2__) if(["default","and","equals","fail","forField","iff","isFail","isPass","isSkip","oneOf","or","pass","required","skip","placeholder"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _protocol_definition__WEBPACK_IMPORTED_MODULE_2__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _protocol_ids__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./protocol-ids */ 57635); /* harmony import */ var _protocol_instance__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./protocol-instance */ 31410); /* harmony import */ var _type_checks__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./type-checks */ 39408); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./types */ 83451); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_types__WEBPACK_IMPORTED_MODULE_6__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_6__) if(["default","and","equals","fail","forField","iff","isFail","isPass","isSkip","oneOf","or","pass","required","skip","placeholder","LEGACY_TAVI_PROTOCOL_IDS","TAVI_PROTOCOL_ID","canonicalProtocolId","isTaviProtocolId","protocolInstance","placeholderHasRelationship"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _types__WEBPACK_IMPORTED_MODULE_6__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /***/ }, /***/ 43403 /*!**********************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/placeholder.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ placeholder: () => (/* binding */ placeholder) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); function placeholder(parameters) { return { ...parameters, id: parameters.id ?? (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])() }; } /***/ }, /***/ 35816 /*!******************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/protocol-definition.ts ***! \******************************************************************/ () { /***/ }, /***/ 57635 /*!***********************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/protocol-ids.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LEGACY_TAVI_PROTOCOL_IDS: () => (/* binding */ LEGACY_TAVI_PROTOCOL_IDS), /* harmony export */ TAVI_PROTOCOL_ID: () => (/* binding */ TAVI_PROTOCOL_ID), /* harmony export */ canonicalProtocolId: () => (/* binding */ canonicalProtocolId), /* harmony export */ isTaviProtocolId: () => (/* binding */ isTaviProtocolId) /* harmony export */ }); /** * Canonical protocol identifiers. Single source of truth: this id is a persisted primary key * (protocol instances, OT payload bindings, work-session documents), so it must never be * redeclared as a literal elsewhere. */ const TAVI_PROTOCOL_ID = '25c57fc1-7b9d-50e0-a611-b6d910f89176'; /** * Ids this protocol shipped under before it was aligned with the annotation manual. Kept so * already-persisted sessions and already-exported OT files stay readable; see the v27 * work-session migration and the OT payload schema's normalizing transform. */ const LEGACY_TAVI_PROTOCOL_IDS = ['55f7e562-ff13-4c9e-8ce4-bbe282054573']; /** True for the current id or any id this protocol previously shipped under. */ function isTaviProtocolId(id) { return id === TAVI_PROTOCOL_ID || LEGACY_TAVI_PROTOCOL_IDS.includes(id); } /** Normalizes any historical TAVI id to the canonical one; other ids pass through unchanged. */ function canonicalProtocolId(id) { return isTaviProtocolId(id) ? TAVI_PROTOCOL_ID : id; } /***/ }, /***/ 31410 /*!****************************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/protocol-instance.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ protocolInstance: () => (/* binding */ protocolInstance) /* harmony export */ }); /** * Create a new ProtocolInstance for the provided ProtocolDefinition * @param definition The definition to create a ProtocolInstance for * @returns */ function protocolInstance(definition) { return { placeholderMappings: {}, protocolId: definition.id }; } /***/ }, /***/ 39408 /*!**********************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/type-checks.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ placeholderHasRelationship: () => (/* binding */ placeholderHasRelationship) /* harmony export */ }); function placeholderHasRelationship(placeholder) { return !!placeholder && 'relationship' in placeholder && placeholder.relationship !== undefined; } /***/ }, /***/ 83451 /*!****************************************************!*\ !*** ./libs/types/src/lib/dtos/protocols/types.ts ***! \****************************************************/ () { /***/ }, /***/ 75023 /*!********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/angle.ts ***! \********************************************************/ () { /***/ }, /***/ 87145 /*!***********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/distance.ts ***! \***********************************************************/ () { /***/ }, /***/ 47516 /*!********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/index.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RELATIONSHIP_SPECS: () => (/* binding */ RELATIONSHIP_SPECS) /* harmony export */ }); /* harmony import */ var _enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../enums */ 66556); /* harmony import */ var _angle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./angle */ 75023); /* harmony import */ var _angle__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_angle__WEBPACK_IMPORTED_MODULE_1__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _angle__WEBPACK_IMPORTED_MODULE_1__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _angle__WEBPACK_IMPORTED_MODULE_1__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _distance__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./distance */ 87145); /* harmony import */ var _distance__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_distance__WEBPACK_IMPORTED_MODULE_2__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _distance__WEBPACK_IMPORTED_MODULE_2__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _distance__WEBPACK_IMPORTED_MODULE_2__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _point__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./point */ 95406); /* harmony import */ var _point__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_point__WEBPACK_IMPORTED_MODULE_3__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _point__WEBPACK_IMPORTED_MODULE_3__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _point__WEBPACK_IMPORTED_MODULE_3__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _spline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spline */ 13639); /* harmony import */ var _spline__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_spline__WEBPACK_IMPORTED_MODULE_4__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _spline__WEBPACK_IMPORTED_MODULE_4__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _spline__WEBPACK_IMPORTED_MODULE_4__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./types */ 8493); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_types__WEBPACK_IMPORTED_MODULE_5__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_5__) if(["default","RELATIONSHIP_SPECS"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _types__WEBPACK_IMPORTED_MODULE_5__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); // This will mostly be used to tell the frontend what type of Relationships // are available for which source types. const RELATIONSHIP_SPECS = { [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE]: { 'angle-between-spline-axes': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE], [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE]] }, 'angle-between-splines': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE], [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE]] } }, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE]: {}, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CYLINDER]: {}, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE]: { 'attached-distance': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] }, 'center-distance': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] }, chord: { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] }, 'closest-distance-between-annotations': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT], [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT]] }, 'closest-distance-to-one-annotation': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] }, 'projected-distance': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE]] } }, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.HOLLOW_CYLINDER]: {}, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]: { 'attached-spline': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] } }, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT]: { 'attached-point': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] }, 'curvature-point': { allowedSourceTypes: [[_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, _enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]] } }, [_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.STL]: {} }; /***/ }, /***/ 95406 /*!********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/point.ts ***! \********************************************************/ () { /***/ }, /***/ 13639 /*!*********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/spline.ts ***! \*********************************************************/ () { /***/ }, /***/ 8493 /*!********************************************************!*\ !*** ./libs/types/src/lib/dtos/relationships/types.ts ***! \********************************************************/ () { /***/ }, /***/ 66469 /*!*******************************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/control-point-s-curve.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ controlPointSCurve: () => (/* binding */ controlPointSCurve) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); function controlPointSCurve(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: 'control-point', ...data }; } /***/ }, /***/ 49089 /*!***************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/index.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEFAULT_S_CURVE_GRAPH_FONT_SIZE: () => (/* reexport safe */ _types__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_S_CURVE_GRAPH_FONT_SIZE), /* harmony export */ DEFAULT_S_CURVE_LINE_WIDTH: () => (/* reexport safe */ _types__WEBPACK_IMPORTED_MODULE_5__.DEFAULT_S_CURVE_LINE_WIDTH), /* harmony export */ controlPointSCurve: () => (/* reexport safe */ _control_point_s_curve__WEBPACK_IMPORTED_MODULE_0__.controlPointSCurve), /* harmony export */ sCurveAngleMeasurement: () => (/* reexport safe */ _relative_measurement__WEBPACK_IMPORTED_MODULE_1__.sCurveAngleMeasurement), /* harmony export */ sCurveIntersectionMeasurement: () => (/* reexport safe */ _relative_measurement__WEBPACK_IMPORTED_MODULE_1__.sCurveIntersectionMeasurement), /* harmony export */ sCurveIsControlPoint: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_4__.sCurveIsControlPoint), /* harmony export */ sCurveIsRelativeMeasurement: () => (/* reexport safe */ _relative_measurement_type_checks__WEBPACK_IMPORTED_MODULE_2__.sCurveIsRelativeMeasurement), /* harmony export */ sCurveIsSpline: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_4__.sCurveIsSpline), /* harmony export */ sCurveIsStub: () => (/* reexport safe */ _type_checks__WEBPACK_IMPORTED_MODULE_4__.sCurveIsStub), /* harmony export */ sCurveMeasurementIsAngle: () => (/* reexport safe */ _relative_measurement_type_checks__WEBPACK_IMPORTED_MODULE_2__.sCurveMeasurementIsAngle), /* harmony export */ sCurveMeasurementIsIntersection: () => (/* reexport safe */ _relative_measurement_type_checks__WEBPACK_IMPORTED_MODULE_2__.sCurveMeasurementIsIntersection), /* harmony export */ splineSCurve: () => (/* reexport safe */ _spline_s_curve__WEBPACK_IMPORTED_MODULE_3__.splineSCurve) /* harmony export */ }); /* harmony import */ var _control_point_s_curve__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./control-point-s-curve */ 66469); /* harmony import */ var _relative_measurement__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./relative-measurement */ 76848); /* harmony import */ var _relative_measurement_type_checks__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./relative-measurement-type-checks */ 86739); /* harmony import */ var _spline_s_curve__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./spline-s-curve */ 98190); /* harmony import */ var _type_checks__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./type-checks */ 14971); /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./types */ 63188); /***/ }, /***/ 86739 /*!******************************************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/relative-measurement-type-checks.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurveIsRelativeMeasurement: () => (/* binding */ sCurveIsRelativeMeasurement), /* harmony export */ sCurveMeasurementIsAngle: () => (/* binding */ sCurveMeasurementIsAngle), /* harmony export */ sCurveMeasurementIsIntersection: () => (/* binding */ sCurveMeasurementIsIntersection) /* harmony export */ }); function sCurveIsRelativeMeasurement(entity) { const candidate = entity; // type alone isn't enough to discriminate: a plain Angle annotation (Annotation union) // also uses type 'angle' (AnnotationSourceType.ANGLE), so anything checking a value that // could be either - like the annotation-menu color swatch - would otherwise misclassify // a real Angle annotation as an SCurveRelativeMeasurement. sourceIds is required on both // SCurveAngleMeasurement and SCurveIntersectionMeasurement and absent from Angle, so it's // a safe, always-present distinguishing field for every genuine measurement. return (candidate?.type === 'angle' || candidate?.type === 'intersection') && Array.isArray(candidate.sourceIds); } function sCurveMeasurementIsAngle(measurement) { return measurement.type === 'angle'; } function sCurveMeasurementIsIntersection(measurement) { return measurement.type === 'intersection'; } /***/ }, /***/ 76848 /*!******************************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/relative-measurement.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurveAngleMeasurement: () => (/* binding */ sCurveAngleMeasurement), /* harmony export */ sCurveIntersectionMeasurement: () => (/* binding */ sCurveIntersectionMeasurement) /* harmony export */ }); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ 69083); function sCurveAngleMeasurement(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: 'angle', ...data }; } function sCurveIntersectionMeasurement(data) { return { id: (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(), type: 'intersection', ...data }; } /***/ }, /***/ 98190 /*!************************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/spline-s-curve.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ splineSCurve: () => (/* binding */ splineSCurve) /* harmony export */ }); function splineSCurve(spline) { return { color: spline.color, hidden: spline.hidden, id: spline.id, name: spline.name, spline, type: 'spline' }; } /***/ }, /***/ 14971 /*!*********************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/type-checks.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurveIsControlPoint: () => (/* binding */ sCurveIsControlPoint), /* harmony export */ sCurveIsSpline: () => (/* binding */ sCurveIsSpline), /* harmony export */ sCurveIsStub: () => (/* binding */ sCurveIsStub) /* harmony export */ }); function sCurveIsControlPoint(scurve) { return scurve.type === 'control-point'; } function sCurveIsSpline(scurve) { return scurve.type === 'spline'; } function sCurveIsStub(scurve) { return scurve.type === 'stub'; } /***/ }, /***/ 63188 /*!***************************************************!*\ !*** ./libs/types/src/lib/dtos/s-curves/types.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEFAULT_S_CURVE_GRAPH_FONT_SIZE: () => (/* binding */ DEFAULT_S_CURVE_GRAPH_FONT_SIZE), /* harmony export */ DEFAULT_S_CURVE_LINE_WIDTH: () => (/* binding */ DEFAULT_S_CURVE_LINE_WIDTH) /* harmony export */ }); // Matches the previous hardcoded stroke-width in the s-curve graph's curve renderer. // General to the graph as a whole (not per-curve) - same as DEFAULT_S_CURVE_GRAPH_FONT_SIZE. const DEFAULT_S_CURVE_LINE_WIDTH = 2; // Matches the previous hardcoded font-size in the s-curve graph's axis/scale labels. const DEFAULT_S_CURVE_GRAPH_FONT_SIZE = 9; /***/ }, /***/ 38504 /*!******************************************************!*\ !*** ./libs/types/src/lib/dtos/tvct-work-session.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TVCT_LEGACY_MANUFACTURER: () => (/* binding */ TVCT_LEGACY_MANUFACTURER), /* harmony export */ TVCT_PRIVATE_CREATOR: () => (/* binding */ TVCT_PRIVATE_CREATOR), /* harmony export */ TVCT_WORK_SESSION_DESCRIPTION_PREFIX: () => (/* binding */ TVCT_WORK_SESSION_DESCRIPTION_PREFIX), /* harmony export */ TVCT_WORK_SESSION_TYPE: () => (/* binding */ TVCT_WORK_SESSION_TYPE), /* harmony export */ isTvctWorkSessionInstance: () => (/* binding */ isTvctWorkSessionInstance), /* harmony export */ isTvctWorkSessionSeries: () => (/* binding */ isTvctWorkSessionSeries), /* harmony export */ toTvctWorkSessionDescription: () => (/* binding */ toTvctWorkSessionDescription) /* harmony export */ }); /* harmony import */ var _enums_dicomweb_enum__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../enums/dicomweb.enum */ 26905); /** * tvCT work-session ("saved analysis") detection. Two formats exist in the wild: * - New (current): OT Secondary Capture with the mandated description prefix and * private tags (0029,0010)=TOMOVERSE_TVCT_1, (0029,1001)=TVCT_WORKSESSION. * - Legacy (deprecated): Enhanced SR with Manufacturer "TOMOVERSE IMAGING". * * Modality=OT alone is NOT a work session. OT is DICOM's generic "Other" and third * parties store OT objects too. */ const TVCT_WORK_SESSION_DESCRIPTION_PREFIX = 'tvCT Analysis Worksession'; const TVCT_PRIVATE_CREATOR = 'TOMOVERSE_TVCT_1'; const TVCT_WORK_SESSION_TYPE = 'TVCT_WORKSESSION'; const TVCT_LEGACY_MANUFACTURER = 'TOMOVERSE IMAGING'; const SERIES_DESCRIPTION_MAX_LENGTH = 64; /** Formats a work-session SeriesDescription with the mandated prefix. */ function toTvctWorkSessionDescription(workSessionName) { const name = workSessionName.trim(); const description = name ? `${TVCT_WORK_SESSION_DESCRIPTION_PREFIX} - ${name}` : TVCT_WORK_SESSION_DESCRIPTION_PREFIX; return description.slice(0, SERIES_DESCRIPTION_MAX_LENGTH); } /** Series-level detection for contexts without instance data (e.g. the study list). */ function isTvctWorkSessionSeries(series) { const modality = series.modality?.trim().toUpperCase(); // Legacy work sessions are the only SR objects tvCT stores write. if (modality === 'SR') return true; return modality === 'OT' && (series.seriesDescription ?? '').startsWith(TVCT_WORK_SESSION_DESCRIPTION_PREFIX); } /** Instance-level detection (definitive), private tags for the new format, Manufacturer for legacy. */ function isTvctWorkSessionInstance(metadata) { const read = tag => String(metadata[tag]?.Value?.[0] ?? '').trim(); const isNewFormat = read(_enums_dicomweb_enum__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TvctPrivateCreator) === TVCT_PRIVATE_CREATOR && read(_enums_dicomweb_enum__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TvctWorkSessionType) === TVCT_WORK_SESSION_TYPE; return isNewFormat || read(_enums_dicomweb_enum__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.Manufacturer).toUpperCase() === TVCT_LEGACY_MANUFACTURER; } /***/ }, /***/ 99455 /*!***********************************************************************!*\ !*** ./libs/types/src/lib/enums/annotation-interaction-state.enum.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationInteractionState: () => (/* binding */ AnnotationInteractionState) /* harmony export */ }); var AnnotationInteractionState; (function (AnnotationInteractionState) { AnnotationInteractionState["ADDING_POINTS"] = "adding-points"; AnnotationInteractionState["BEING_CREATED"] = "being-created"; AnnotationInteractionState["DESELECTED"] = "deselected"; AnnotationInteractionState["HOVER"] = "hover"; AnnotationInteractionState["SELECTED"] = "selected"; })(AnnotationInteractionState || (AnnotationInteractionState = {})); /***/ }, /***/ 31935 /*!*****************************************************************!*\ !*** ./libs/types/src/lib/enums/annotation-source-type.enum.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationSourceType: () => (/* binding */ AnnotationSourceType) /* harmony export */ }); var AnnotationSourceType; (function (AnnotationSourceType) { AnnotationSourceType["ANGLE"] = "angle"; AnnotationSourceType["CLOSED_SPLINE"] = "closed-spline"; AnnotationSourceType["CYLINDER"] = "cylinder"; AnnotationSourceType["DISTANCE"] = "distance"; AnnotationSourceType["HOLLOW_CYLINDER"] = "hollow-cylinder"; AnnotationSourceType["OPEN_SPLINE"] = "open-spline"; AnnotationSourceType["POINT"] = "point"; AnnotationSourceType["STL"] = "stl"; })(AnnotationSourceType || (AnnotationSourceType = {})); /***/ }, /***/ 33545 /*!*****************************************************!*\ !*** ./libs/types/src/lib/enums/card-state.enum.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CardState: () => (/* binding */ CardState) /* harmony export */ }); var CardState; (function (CardState) { CardState["DEFAULT"] = "default"; CardState["DISABLED"] = "disabled"; CardState["SELECTED"] = "selected"; })(CardState || (CardState = {})); /***/ }, /***/ 70660 /*!*******************************************************!*\ !*** ./libs/types/src/lib/enums/dicom-vendor.enum.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomVendor: () => (/* binding */ DicomVendor) /* harmony export */ }); var DicomVendor; (function (DicomVendor) { DicomVendor["GOOGLE_HEALTHCARE"] = "google-healthcare"; DicomVendor["ORTHANC"] = "orthanc"; })(DicomVendor || (DicomVendor = {})); /***/ }, /***/ 26905 /*!***************************************************!*\ !*** ./libs/types/src/lib/enums/dicomweb.enum.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomTagId: () => (/* binding */ DicomTagId), /* harmony export */ TransferSyntaxUID: () => (/* binding */ TransferSyntaxUID) /* harmony export */ }); const DicomTagId = { AccessionNumber: '00080050', AcquisitionNumber: '00200012', ApprovalStatus: '300E0002', BitsAllocated: '00280100', BitsStored: '00280101', // CARDIAC GATING CardiacNumberOfImages: '00181090', CardiacSynchronizationSequence: '00189118', Columns: '00280011', FrameTime: '00181063', HeartRate: '00181088', HighBit: '00280102', ImageOrientationPatient: '00200037', // GEOMETRY (Needed for Orthographic/MPR) ImagePositionPatient: '00200032', InstanceCreationDate: '00080012', InstanceCreationTime: '00080013', InstanceNumber: '00200013', InstitutionName: '00080080', Manufacturer: '00080070', ModalitiesInStudy: '00080061', Modality: '00080060', NominalCardiacTriggerDelayTime: '00209153', NominalInterval: '00181062', NominalPercentageOfCardiacPhase: '00209241', NumberOfFrames: '00280008', NumberOfPhases: '00540031', NumberOfSeriesRelatedInstances: '00201209', NumberOfStudyRelatedInstances: '00201208', NumberOfStudyRelatedSeries: '00201206', // MULTI-VOLUME / 4D NumberOfTemporalPositions: '00200105', PatientBirthDate: '00100030', PatientID: '00100020', PatientName: '00100010', PatientSex: '00100040', PerFrameFunctionalGroupsSequence: '52009230', PhaseVector: '00181064', PhotometricInterpretation: '00280004', PixelRepresentation: '00280103', PixelSpacing: '00280030', ReferencedSeriesSequence: '00081115', ReferringPhysicianName: '00080090', RescaleIntercept: '00281052', RescaleSlope: '00281053', RetrieveURL: '00081190', // IMAGE PIXEL MODULE Rows: '00280010', SamplesPerPixel: '00280002', // SIEMENS encodes cardiac phase here as a backslash-joined array with a "TPPC" token. ScanOptions: '00180022', SeriesDate: '00080021', SeriesDescription: '0008103E', SeriesInstanceUID: '0020000E', SeriesNumber: '00200011', SeriesTime: '00080031', SharedFunctionalGroupsSequence: '52009229', SliceLocation: '00201041', SliceThickness: '00180050', SOPInstanceUID: '00080018', SpecificCharacterSet: '00080005', StageName: '00082120', StudyDate: '00080020', StudyDescription: '00081030', StudyID: '00200010', StudyInstanceUID: '0020000D', StudyTime: '00080030', TemporalPositionIdentifier: '00200100', TransferSyntaxUID: '00041512', TriggerTime: '00181060', TvctAuthorName: '00291012', TvctPhaseLabel: '00291019', TvctPrivateCreator: '00290010', TvctReviewStatus: '00291014', TvctWorkSessionType: '00291001', TvctWorkSessionUid: '00291003', // WINDOWING / VOI LUT WindowCenter: '00281050', WindowWidth: '00281051' }; var TransferSyntaxUID; (function (TransferSyntaxUID) { TransferSyntaxUID["DeflatedExplicitVRLittleEndian"] = "1.2.840.10008.1.2.1.99"; TransferSyntaxUID["ExplicitVRBigEndian"] = "1.2.840.10008.1.2.2"; TransferSyntaxUID["ExplicitVRLittleEndian"] = "1.2.840.10008.1.2.1"; TransferSyntaxUID["HTJ2K"] = "1.2.840.10008.1.2.4.203"; // --- High-Throughput JPEG 2000 (HTJ2K) --- TransferSyntaxUID["HTJ2KLosslessOnly"] = "1.2.840.10008.1.2.4.201"; TransferSyntaxUID["HTJ2KRPCLOptionsLosslessOnly"] = "1.2.840.10008.1.2.4.202"; // --- Uncompressed / Endian --- TransferSyntaxUID["ImplicitVRLittleEndian"] = "1.2.840.10008.1.2"; TransferSyntaxUID["JPEG2000"] = "1.2.840.10008.1.2.4.91"; // --- JPEG 2000 --- TransferSyntaxUID["JPEG2000LosslessOnly"] = "1.2.840.10008.1.2.4.90"; TransferSyntaxUID["JPEG2000Part2Multicomponent"] = "1.2.840.10008.1.2.4.93"; TransferSyntaxUID["JPEG2000Part2MulticomponentLosslessOnly"] = "1.2.840.10008.1.2.4.92"; // --- JPEG Process 1 - 29 --- TransferSyntaxUID["JPEGBaselineProcess1"] = "1.2.840.10008.1.2.4.50"; TransferSyntaxUID["JPEGBaselineProcess2_4"] = "1.2.840.10008.1.2.4.51"; TransferSyntaxUID["JPEGExtendedHierarchicalProcess16_18"] = "1.2.840.10008.1.2.4.59"; TransferSyntaxUID["JPEGExtendedHierarchicalProcess17_19"] = "1.2.840.10008.1.2.4.60"; TransferSyntaxUID["JPEGExtendedProcess3_5"] = "1.2.840.10008.1.2.4.52"; TransferSyntaxUID["JPEGFullProgressionHierarchicalProcess24_26"] = "1.2.840.10008.1.2.4.63"; TransferSyntaxUID["JPEGFullProgressionHierarchicalProcess25_27"] = "1.2.840.10008.1.2.4.64"; TransferSyntaxUID["JPEGFullProgressionNonHierarchicalProcess10_12"] = "1.2.840.10008.1.2.4.55"; TransferSyntaxUID["JPEGFullProgressionNonHierarchicalProcess11_13"] = "1.2.840.10008.1.2.4.56"; TransferSyntaxUID["JPEGLosslessFirstOrderPrediction"] = "1.2.840.10008.1.2.4.70"; TransferSyntaxUID["JPEGLosslessNonHierarchicalProcess14"] = "1.2.840.10008.1.2.4.57"; TransferSyntaxUID["JPEGLosslessNonHierarchicalProcess15"] = "1.2.840.10008.1.2.4.58"; TransferSyntaxUID["JPEGLosslessNonHierarchicalProcess28"] = "1.2.840.10008.1.2.4.65"; TransferSyntaxUID["JPEGLosslessNonHierarchicalProcess29"] = "1.2.840.10008.1.2.4.66"; // --- JPEG-LS --- TransferSyntaxUID["JPEGLSLossless"] = "1.2.840.10008.1.2.4.80"; TransferSyntaxUID["JPEGLSLossy"] = "1.2.840.10008.1.2.4.81"; TransferSyntaxUID["JPEGSpectralSelectionHierarchicalProcess20_22"] = "1.2.840.10008.1.2.4.61"; TransferSyntaxUID["JPEGSpectralSelectionHierarchicalProcess21_23"] = "1.2.840.10008.1.2.4.62"; TransferSyntaxUID["JPEGSpectralSelectionNonHierarchicalProcess6_8"] = "1.2.840.10008.1.2.4.53"; TransferSyntaxUID["JPEGSpectralSelectionNonHierarchicalProcess7_9"] = "1.2.840.10008.1.2.4.54"; // --- JPIP --- TransferSyntaxUID["JPIPReferenced"] = "1.2.840.10008.1.2.4.94"; TransferSyntaxUID["JPIPReferencedDeflate"] = "1.2.840.10008.1.2.4.95"; // --- Video Compression (MPEG) --- TransferSyntaxUID["MPEG2MainProfileMainLevel"] = "1.2.840.10008.1.2.4.100"; TransferSyntaxUID["MPEG4AVCH264BDCompatibleHighProfileLevel41"] = "1.2.840.10008.1.2.4.103"; TransferSyntaxUID["MPEG4AVCH264HighProfileLevel41"] = "1.2.840.10008.1.2.4.102"; TransferSyntaxUID["RFC2557MIMEEncapsulation"] = "1.2.840.10008.1.2.6.1"; // --- RLE and MIME --- TransferSyntaxUID["RLELossless"] = "1.2.840.10008.1.2.5"; })(TransferSyntaxUID || (TransferSyntaxUID = {})); /***/ }, /***/ 66556 /*!*******************************************!*\ !*** ./libs/types/src/lib/enums/index.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnnotationInteractionState: () => (/* reexport safe */ _annotation_interaction_state_enum__WEBPACK_IMPORTED_MODULE_1__.AnnotationInteractionState), /* harmony export */ AnnotationSourceType: () => (/* reexport safe */ _annotation_source_type_enum__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType), /* harmony export */ CardState: () => (/* reexport safe */ _card_state_enum__WEBPACK_IMPORTED_MODULE_21__.CardState), /* harmony export */ DicomTagId: () => (/* reexport safe */ _dicomweb_enum__WEBPACK_IMPORTED_MODULE_2__.DicomTagId), /* harmony export */ DicomVendor: () => (/* reexport safe */ _dicom_vendor_enum__WEBPACK_IMPORTED_MODULE_3__.DicomVendor), /* harmony export */ InteractionModeType: () => (/* reexport safe */ _interaction_mode_type_enum__WEBPACK_IMPORTED_MODULE_4__.InteractionModeType), /* harmony export */ LayoutType: () => (/* reexport safe */ _layout_type_enum__WEBPACK_IMPORTED_MODULE_5__.LayoutType), /* harmony export */ MeasurementName: () => (/* reexport safe */ _measurement_name_enum__WEBPACK_IMPORTED_MODULE_6__.MeasurementName), /* harmony export */ OrientationAxis: () => (/* reexport safe */ _viewport_orientation_axis_enum__WEBPACK_IMPORTED_MODULE_17__.OrientationAxis), /* harmony export */ PanelName: () => (/* reexport safe */ _panel_name_enum__WEBPACK_IMPORTED_MODULE_7__.PanelName), /* harmony export */ Provider: () => (/* reexport safe */ _provider_enum__WEBPACK_IMPORTED_MODULE_8__.Provider), /* harmony export */ RxDBSyncStatus: () => (/* reexport safe */ _rxdb_sync_status_enum__WEBPACK_IMPORTED_MODULE_19__.RxDBSyncStatus), /* harmony export */ SelectOptionsTemplate: () => (/* reexport safe */ _select_options_template_enum__WEBPACK_IMPORTED_MODULE_20__.SelectOptionsTemplate), /* harmony export */ SettingsPopoverField: () => (/* reexport safe */ _settings_popover_field_enum__WEBPACK_IMPORTED_MODULE_10__.SettingsPopoverField), /* harmony export */ SidebarSection: () => (/* reexport safe */ _right_sidebar_section_enum__WEBPACK_IMPORTED_MODULE_9__.SidebarSection), /* harmony export */ SliderSourceType: () => (/* reexport safe */ _slider_source_type_enum__WEBPACK_IMPORTED_MODULE_12__.SliderSourceType), /* harmony export */ StoreType: () => (/* reexport safe */ _store_type_enum__WEBPACK_IMPORTED_MODULE_11__.StoreType), /* harmony export */ TransferSyntaxUID: () => (/* reexport safe */ _dicomweb_enum__WEBPACK_IMPORTED_MODULE_2__.TransferSyntaxUID), /* harmony export */ VascularSegmentationState: () => (/* reexport safe */ _vascular_segmentation_state_enum__WEBPACK_IMPORTED_MODULE_22__.VascularSegmentationState), /* harmony export */ ViewportAxis: () => (/* reexport safe */ _viewport_axis_enum__WEBPACK_IMPORTED_MODULE_13__.ViewportAxis), /* harmony export */ ViewportAxisState: () => (/* reexport safe */ _viewport_axis_state_enum__WEBPACK_IMPORTED_MODULE_14__.ViewportAxisState), /* harmony export */ ViewportName: () => (/* reexport safe */ _viewport_name_enum__WEBPACK_IMPORTED_MODULE_15__.ViewportName), /* harmony export */ ViewportType: () => (/* reexport safe */ _viewport_type_enum__WEBPACK_IMPORTED_MODULE_16__.ViewportType), /* harmony export */ VolumeRenderingOption: () => (/* reexport safe */ _volume_rendering_option_enum__WEBPACK_IMPORTED_MODULE_18__.VolumeRenderingOption), /* harmony export */ isProjectionPreset: () => (/* reexport safe */ _volume_rendering_option_enum__WEBPACK_IMPORTED_MODULE_18__.isProjectionPreset), /* harmony export */ isViewportAxis: () => (/* reexport safe */ _viewport_axis_enum__WEBPACK_IMPORTED_MODULE_13__.isViewportAxis), /* harmony export */ parseVolumeRenderingOption: () => (/* reexport safe */ _volume_rendering_option_enum__WEBPACK_IMPORTED_MODULE_18__.parseVolumeRenderingOption) /* harmony export */ }); /* harmony import */ var _annotation_source_type_enum__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-source-type.enum */ 31935); /* harmony import */ var _annotation_interaction_state_enum__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./annotation-interaction-state.enum */ 99455); /* harmony import */ var _dicomweb_enum__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./dicomweb.enum */ 26905); /* harmony import */ var _dicom_vendor_enum__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dicom-vendor.enum */ 70660); /* harmony import */ var _interaction_mode_type_enum__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./interaction-mode-type.enum */ 61024); /* harmony import */ var _layout_type_enum__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./layout-type.enum */ 60482); /* harmony import */ var _measurement_name_enum__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./measurement-name.enum */ 43903); /* harmony import */ var _panel_name_enum__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./panel-name.enum */ 67477); /* harmony import */ var _provider_enum__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./provider.enum */ 65508); /* harmony import */ var _right_sidebar_section_enum__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./right-sidebar-section.enum */ 31482); /* harmony import */ var _settings_popover_field_enum__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./settings-popover-field.enum */ 50867); /* harmony import */ var _store_type_enum__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./store-type.enum */ 4411); /* harmony import */ var _slider_source_type_enum__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./slider-source-type.enum */ 26639); /* harmony import */ var _viewport_axis_enum__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./viewport-axis.enum */ 92625); /* harmony import */ var _viewport_axis_state_enum__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./viewport-axis-state.enum */ 19113); /* harmony import */ var _viewport_name_enum__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./viewport-name.enum */ 1519); /* harmony import */ var _viewport_type_enum__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./viewport-type.enum */ 35394); /* harmony import */ var _viewport_orientation_axis_enum__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./viewport-orientation-axis.enum */ 65054); /* harmony import */ var _volume_rendering_option_enum__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./volume-rendering-option.enum */ 84452); /* harmony import */ var _rxdb_sync_status_enum__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./rxdb-sync-status.enum */ 82316); /* harmony import */ var _select_options_template_enum__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./select-options-template.enum */ 72661); /* harmony import */ var _card_state_enum__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./card-state.enum */ 33545); /* harmony import */ var _vascular_segmentation_state_enum__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./vascular-segmentation-state.enum */ 52935); /***/ }, /***/ 61024 /*!****************************************************************!*\ !*** ./libs/types/src/lib/enums/interaction-mode-type.enum.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ InteractionModeType: () => (/* binding */ InteractionModeType) /* harmony export */ }); var InteractionModeType; (function (InteractionModeType) { InteractionModeType["ADD_POINTS"] = "add-points"; InteractionModeType["CREATE"] = "create"; InteractionModeType["SELECT"] = "select"; })(InteractionModeType || (InteractionModeType = {})); /***/ }, /***/ 60482 /*!******************************************************!*\ !*** ./libs/types/src/lib/enums/layout-type.enum.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ LayoutType: () => (/* binding */ LayoutType) /* harmony export */ }); var LayoutType; (function (LayoutType) { LayoutType["CPR"] = "cpr"; LayoutType["DEFAULT"] = "default"; LayoutType["MAXIMIZE_3D"] = "focus-on-3d"; LayoutType["MAXIMIZE_AXIAL"] = "focus-on-axial"; LayoutType["MAXIMIZE_CORONAL"] = "focus-on-coronal"; LayoutType["MAXIMIZE_S_CURVE"] = "focus-on-s-curve"; LayoutType["MAXIMIZE_SAGITTAL"] = "focus-on-sagittal"; })(LayoutType || (LayoutType = {})); /***/ }, /***/ 43903 /*!***********************************************************!*\ !*** ./libs/types/src/lib/enums/measurement-name.enum.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MeasurementName: () => (/* binding */ MeasurementName) /* harmony export */ }); var MeasurementName; (function (MeasurementName) { MeasurementName["ANGLE"] = "angle"; MeasurementName["AREA"] = "area"; MeasurementName["BIFURCATION_POSITION"] = "bifurcation-position"; MeasurementName["DISTANCE"] = "distance"; MeasurementName["EN_FACE_VIEW"] = "en-face-view"; MeasurementName["HEIGHT"] = "height"; MeasurementName["LENGTH"] = "length"; MeasurementName["MAXIMUM_DIAMETER"] = "maximum-diameter"; MeasurementName["PERIMETER"] = "perimeter"; MeasurementName["PIXEL_VALUE"] = "pixel-value"; MeasurementName["POSITION"] = "position"; MeasurementName["POSITION_ALONG_SPLINE"] = "position-along-spline"; MeasurementName["RADIUS_OF_CURVATURE"] = "radius-of-curvature"; })(MeasurementName || (MeasurementName = {})); /***/ }, /***/ 67477 /*!*****************************************************!*\ !*** ./libs/types/src/lib/enums/panel-name.enum.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PanelName: () => (/* binding */ PanelName) /* harmony export */ }); var PanelName; (function (PanelName) { PanelName["S_CURVE_GRAPH"] = "s-curve-graph"; })(PanelName || (PanelName = {})); /***/ }, /***/ 65508 /*!***************************************************!*\ !*** ./libs/types/src/lib/enums/provider.enum.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Provider: () => (/* binding */ Provider) /* harmony export */ }); var Provider; (function (Provider) { Provider["GOOGLE"] = "google"; Provider["LOCAL"] = "local"; })(Provider || (Provider = {})); /***/ }, /***/ 31482 /*!****************************************************************!*\ !*** ./libs/types/src/lib/enums/right-sidebar-section.enum.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SidebarSection: () => (/* binding */ SidebarSection) /* harmony export */ }); var SidebarSection; (function (SidebarSection) { SidebarSection["ANNOTATION"] = "annotation"; SidebarSection["CHAMBER"] = "chamber"; SidebarSection["PLANAR_REFORMATION"] = "planar-reformation"; SidebarSection["PROTOCOL"] = "protocol"; SidebarSection["SCAN"] = "scan"; SidebarSection["SCURVE"] = "s-curve"; })(SidebarSection || (SidebarSection = {})); /***/ }, /***/ 82316 /*!***********************************************************!*\ !*** ./libs/types/src/lib/enums/rxdb-sync-status.enum.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RxDBSyncStatus: () => (/* binding */ RxDBSyncStatus) /* harmony export */ }); var RxDBSyncStatus; (function (RxDBSyncStatus) { RxDBSyncStatus["LOCAL"] = "local"; RxDBSyncStatus["SYNCED"] = "synced"; RxDBSyncStatus["UPLOADING"] = "uploading"; })(RxDBSyncStatus || (RxDBSyncStatus = {})); /***/ }, /***/ 72661 /*!******************************************************************!*\ !*** ./libs/types/src/lib/enums/select-options-template.enum.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SelectOptionsTemplate: () => (/* binding */ SelectOptionsTemplate) /* harmony export */ }); var SelectOptionsTemplate; (function (SelectOptionsTemplate) { SelectOptionsTemplate["CT_SELECT_OPTIONS"] = "ct-select-options"; })(SelectOptionsTemplate || (SelectOptionsTemplate = {})); /***/ }, /***/ 50867 /*!*****************************************************************!*\ !*** ./libs/types/src/lib/enums/settings-popover-field.enum.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SettingsPopoverField: () => (/* binding */ SettingsPopoverField) /* harmony export */ }); var SettingsPopoverField; (function (SettingsPopoverField) { SettingsPopoverField["BUTTON"] = "button"; SettingsPopoverField["MENU_BUTTON"] = "menu-button"; SettingsPopoverField["SELECT"] = "select"; SettingsPopoverField["SLIDER"] = "slider"; SettingsPopoverField["TOGGLE"] = "toggle"; })(SettingsPopoverField || (SettingsPopoverField = {})); /***/ }, /***/ 26639 /*!*************************************************************!*\ !*** ./libs/types/src/lib/enums/slider-source-type.enum.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SliderSourceType: () => (/* binding */ SliderSourceType) /* harmony export */ }); var SliderSourceType; (function (SliderSourceType) { SliderSourceType["CCSLIDER"] = "cc-angle-slider"; SliderSourceType["RLSLIDER"] = "rl-angle-slider"; })(SliderSourceType || (SliderSourceType = {})); /***/ }, /***/ 4411 /*!*****************************************************!*\ !*** ./libs/types/src/lib/enums/store-type.enum.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ StoreType: () => (/* binding */ StoreType) /* harmony export */ }); /** Connection category of a DICOM store. */ var StoreType; (function (StoreType) { StoreType["CLOUD"] = "cloud"; StoreType["DICOM_WEB"] = "dicomweb"; StoreType["DIMSE"] = "dimse"; })(StoreType || (StoreType = {})); /***/ }, /***/ 52935 /*!**********************************************************************!*\ !*** ./libs/types/src/lib/enums/vascular-segmentation-state.enum.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VascularSegmentationState: () => (/* binding */ VascularSegmentationState) /* harmony export */ }); /** Where the vascular segmentation flow currently is for the loaded volume. */ var VascularSegmentationState; (function (VascularSegmentationState) { VascularSegmentationState["APPLIED"] = "applied"; VascularSegmentationState["NONE"] = "none"; VascularSegmentationState["PREVIEWING"] = "previewing"; })(VascularSegmentationState || (VascularSegmentationState = {})); /***/ }, /***/ 19113 /*!**************************************************************!*\ !*** ./libs/types/src/lib/enums/viewport-axis-state.enum.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportAxisState: () => (/* binding */ ViewportAxisState) /* harmony export */ }); /* eslint-disable sonarjs/no-commented-code */ // export enum ViewportAxisState { // ALTERNATEBOTTOMLEFT = 'alt-bottom-left', // ALTERNATETOPLEFTMAIN = 'alt-top-left', // BOTTOMLEFTMAIN = 'bottom-left', // MIDDLEMAIN = 'middle', // RIGHTMAIN = 'right', // TOPLEFTMAIN = 'top-left', // } // Temporary values so that the RxDB schema passes until we refactor var ViewportAxisState; (function (ViewportAxisState) { ViewportAxisState["ALTERNATEBOTTOMLEFT"] = "viewportASagittal"; ViewportAxisState["ALTERNATETOPLEFTMAIN"] = "viewportAAxial"; ViewportAxisState["BOTTOMLEFTMAIN"] = "viewportSagittal"; ViewportAxisState["MIDDLEMAIN"] = "viewportCoronal"; ViewportAxisState["RIGHTMAIN"] = "viewport3d"; ViewportAxisState["TOPLEFTMAIN"] = "viewportAxial"; })(ViewportAxisState || (ViewportAxisState = {})); /***/ }, /***/ 92625 /*!********************************************************!*\ !*** ./libs/types/src/lib/enums/viewport-axis.enum.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportAxis: () => (/* binding */ ViewportAxis), /* harmony export */ isViewportAxis: () => (/* binding */ isViewportAxis) /* harmony export */ }); var ViewportAxis; (function (ViewportAxis) { ViewportAxis["AXIAL"] = "axial"; ViewportAxis["CORONAL"] = "coronal"; ViewportAxis["SAGITTAL"] = "sagittal"; })(ViewportAxis || (ViewportAxis = {})); function isViewportAxis(ing_) { return [ViewportAxis.AXIAL, ViewportAxis.CORONAL, ViewportAxis.SAGITTAL].includes(ing_); } /***/ }, /***/ 1519 /*!********************************************************!*\ !*** ./libs/types/src/lib/enums/viewport-name.enum.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportName: () => (/* binding */ ViewportName) /* harmony export */ }); var ViewportName; (function (ViewportName) { ViewportName["AXIAL"] = "axial"; ViewportName["CORONAL"] = "coronal"; ViewportName["REFORMAT"] = "reformat"; ViewportName["SAGITTAL"] = "sagittal"; })(ViewportName || (ViewportName = {})); /***/ }, /***/ 65054 /*!********************************************************************!*\ !*** ./libs/types/src/lib/enums/viewport-orientation-axis.enum.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OrientationAxis: () => (/* binding */ OrientationAxis) /* harmony export */ }); var OrientationAxis; (function (OrientationAxis) { OrientationAxis["ACQUISITION"] = "acquisition"; OrientationAxis["AXIAL"] = "axial"; OrientationAxis["AXIAL_REFORMAT"] = "axial_reformat"; OrientationAxis["CORONAL"] = "coronal"; OrientationAxis["CORONAL_REFORMAT"] = "coronal_reformat"; OrientationAxis["REFORMAT"] = "reformat"; OrientationAxis["SAGITTAL"] = "sagittal"; OrientationAxis["SAGITTAL_REFORMAT"] = "sagittal_reformat"; })(OrientationAxis || (OrientationAxis = {})); /***/ }, /***/ 35394 /*!********************************************************!*\ !*** ./libs/types/src/lib/enums/viewport-type.enum.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportType: () => (/* binding */ ViewportType) /* harmony export */ }); var ViewportType; (function (ViewportType) { ViewportType["ORTHOGRAPHIC"] = "orthographic"; ViewportType["PERSPECTIVE"] = "perspective"; ViewportType["VOLUME_3D"] = "volume3d"; })(ViewportType || (ViewportType = {})); /***/ }, /***/ 84452 /*!******************************************************************!*\ !*** ./libs/types/src/lib/enums/volume-rendering-option.enum.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeRenderingOption: () => (/* binding */ VolumeRenderingOption), /* harmony export */ isProjectionPreset: () => (/* binding */ isProjectionPreset), /* harmony export */ parseVolumeRenderingOption: () => (/* binding */ parseVolumeRenderingOption) /* harmony export */ }); var VolumeRenderingOption; (function (VolumeRenderingOption) { VolumeRenderingOption["ENDO"] = "CT-Cardiac3"; VolumeRenderingOption["FLUOROSCOPIC"] = "CT-MIP"; VolumeRenderingOption["MIP"] = "CT-MaxIP"; VolumeRenderingOption["VASCULAR"] = "CT-Vascular"; VolumeRenderingOption["XRAY"] = "CT-Bone"; })(VolumeRenderingOption || (VolumeRenderingOption = {})); function parseVolumeRenderingOption(value) { return Object.values(VolumeRenderingOption).find(v => v === value); } function isProjectionPreset(value) { return value === VolumeRenderingOption.FLUOROSCOPIC || value === VolumeRenderingOption.XRAY || value === VolumeRenderingOption.MIP; } /***/ }, /***/ 3807 /*!***********************************************!*\ !*** ./libs/types/src/lib/types/aabb.type.ts ***! \***********************************************/ () { /***/ }, /***/ 63727 /*!*****************************************************!*\ !*** ./libs/types/src/lib/types/angulation.type.ts ***! \*****************************************************/ () { /***/ }, /***/ 75507 /*!*******************************************************************!*\ !*** ./libs/types/src/lib/types/annotation-actor-details.type.ts ***! \*******************************************************************/ () { /***/ }, /***/ 74598 /*!*************************************************************!*\ !*** ./libs/types/src/lib/types/annotation-updater.type.ts ***! \*************************************************************/ () { /***/ }, /***/ 92652 /*!*******************************************************!*\ !*** ./libs/types/src/lib/types/camera-state.type.ts ***! \*******************************************************/ () { /***/ }, /***/ 96528 /*!*****************************************************!*\ !*** ./libs/types/src/lib/types/click-info.type.ts ***! \*****************************************************/ () { /***/ }, /***/ 58525 /*!*************************************************************!*\ !*** ./libs/types/src/lib/types/context-menu-items.type.ts ***! \*************************************************************/ () { /***/ }, /***/ 58018 /*!***********************************************************!*\ !*** ./libs/types/src/lib/types/convex-hull-mesh.type.ts ***! \***********************************************************/ () { /***/ }, /***/ 22752 /*!*******************************************************!*\ !*** ./libs/types/src/lib/types/current-user.type.ts ***! \*******************************************************/ () { /***/ }, /***/ 47680 /*!******************************************************!*\ !*** ./libs/types/src/lib/types/dialog-data.type.ts ***! \******************************************************/ () { /***/ }, /***/ 58513 /*!*************************************************************!*\ !*** ./libs/types/src/lib/types/dicom-importer-row.type.ts ***! \*************************************************************/ () { /***/ }, /***/ 7629 /*!*********************************************************************!*\ !*** ./libs/types/src/lib/types/dicom-naturalized-data-set.type.ts ***! \*********************************************************************/ () { /***/ }, /***/ 45965 /*!**********************************************!*\ !*** ./libs/types/src/lib/types/dicomweb.ts ***! \**********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getTagValue: () => (/* binding */ getTagValue) /* harmony export */ }); /* harmony import */ var _enums_dicomweb_enum__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../enums/dicomweb.enum */ 26905); function getTagValue(dicomEntity, tagId) { return dicomEntity[tagId]?.Value?.[0]; } /***/ }, /***/ 88392 /*!*******************************************************!*\ !*** ./libs/types/src/lib/types/electron-api.type.ts ***! \*******************************************************/ () { /***/ }, /***/ 5819 /*!************************************************************!*\ !*** ./libs/types/src/lib/types/hardware-selector.type.ts ***! \************************************************************/ () { /***/ }, /***/ 25575 /*!*******************************************!*\ !*** ./libs/types/src/lib/types/index.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getTagValue: () => (/* reexport safe */ _dicomweb__WEBPACK_IMPORTED_MODULE_10__.getTagValue) /* harmony export */ }); /* harmony import */ var _aabb_type__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./aabb.type */ 3807); /* harmony import */ var _aabb_type__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_aabb_type__WEBPACK_IMPORTED_MODULE_0__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _aabb_type__WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _aabb_type__WEBPACK_IMPORTED_MODULE_0__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _angulation_type__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./angulation.type */ 63727); /* harmony import */ var _angulation_type__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_angulation_type__WEBPACK_IMPORTED_MODULE_1__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _angulation_type__WEBPACK_IMPORTED_MODULE_1__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _angulation_type__WEBPACK_IMPORTED_MODULE_1__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _annotation_actor_details_type__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotation-actor-details.type */ 75507); /* harmony import */ var _annotation_actor_details_type__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_annotation_actor_details_type__WEBPACK_IMPORTED_MODULE_2__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _annotation_actor_details_type__WEBPACK_IMPORTED_MODULE_2__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _annotation_actor_details_type__WEBPACK_IMPORTED_MODULE_2__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _annotation_updater_type__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./annotation-updater.type */ 74598); /* harmony import */ var _annotation_updater_type__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_annotation_updater_type__WEBPACK_IMPORTED_MODULE_3__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _annotation_updater_type__WEBPACK_IMPORTED_MODULE_3__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _annotation_updater_type__WEBPACK_IMPORTED_MODULE_3__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _camera_state_type__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./camera-state.type */ 92652); /* harmony import */ var _camera_state_type__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_camera_state_type__WEBPACK_IMPORTED_MODULE_4__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _camera_state_type__WEBPACK_IMPORTED_MODULE_4__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _camera_state_type__WEBPACK_IMPORTED_MODULE_4__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _click_info_type__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./click-info.type */ 96528); /* harmony import */ var _click_info_type__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_click_info_type__WEBPACK_IMPORTED_MODULE_5__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _click_info_type__WEBPACK_IMPORTED_MODULE_5__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _click_info_type__WEBPACK_IMPORTED_MODULE_5__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _context_menu_items_type__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./context-menu-items.type */ 58525); /* harmony import */ var _context_menu_items_type__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_context_menu_items_type__WEBPACK_IMPORTED_MODULE_6__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _context_menu_items_type__WEBPACK_IMPORTED_MODULE_6__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _context_menu_items_type__WEBPACK_IMPORTED_MODULE_6__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _convex_hull_mesh_type__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./convex-hull-mesh.type */ 58018); /* harmony import */ var _convex_hull_mesh_type__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_convex_hull_mesh_type__WEBPACK_IMPORTED_MODULE_7__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _convex_hull_mesh_type__WEBPACK_IMPORTED_MODULE_7__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _convex_hull_mesh_type__WEBPACK_IMPORTED_MODULE_7__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _current_user_type__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./current-user.type */ 22752); /* harmony import */ var _current_user_type__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_current_user_type__WEBPACK_IMPORTED_MODULE_8__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _current_user_type__WEBPACK_IMPORTED_MODULE_8__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _current_user_type__WEBPACK_IMPORTED_MODULE_8__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _dialog_data_type__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./dialog-data.type */ 47680); /* harmony import */ var _dialog_data_type__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_dialog_data_type__WEBPACK_IMPORTED_MODULE_9__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _dialog_data_type__WEBPACK_IMPORTED_MODULE_9__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _dialog_data_type__WEBPACK_IMPORTED_MODULE_9__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _dicomweb__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./dicomweb */ 45965); /* harmony import */ var _electron_api_type__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./electron-api.type */ 88392); /* harmony import */ var _electron_api_type__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_electron_api_type__WEBPACK_IMPORTED_MODULE_11__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _electron_api_type__WEBPACK_IMPORTED_MODULE_11__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _electron_api_type__WEBPACK_IMPORTED_MODULE_11__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _hardware_selector_type__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./hardware-selector.type */ 5819); /* harmony import */ var _hardware_selector_type__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_hardware_selector_type__WEBPACK_IMPORTED_MODULE_12__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _hardware_selector_type__WEBPACK_IMPORTED_MODULE_12__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _hardware_selector_type__WEBPACK_IMPORTED_MODULE_12__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _interaction_mode_type__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./interaction-mode.type */ 61197); /* harmony import */ var _interaction_mode_type__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_interaction_mode_type__WEBPACK_IMPORTED_MODULE_13__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _interaction_mode_type__WEBPACK_IMPORTED_MODULE_13__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _interaction_mode_type__WEBPACK_IMPORTED_MODULE_13__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _object3d_geometry_type__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./object3d-geometry.type */ 98088); /* harmony import */ var _object3d_geometry_type__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(_object3d_geometry_type__WEBPACK_IMPORTED_MODULE_14__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _object3d_geometry_type__WEBPACK_IMPORTED_MODULE_14__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _object3d_geometry_type__WEBPACK_IMPORTED_MODULE_14__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _measurement_type__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./measurement.type */ 69553); /* harmony import */ var _measurement_type__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(_measurement_type__WEBPACK_IMPORTED_MODULE_15__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _measurement_type__WEBPACK_IMPORTED_MODULE_15__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _measurement_type__WEBPACK_IMPORTED_MODULE_15__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _mutable_type__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./mutable.type */ 32727); /* harmony import */ var _mutable_type__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(_mutable_type__WEBPACK_IMPORTED_MODULE_16__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _mutable_type__WEBPACK_IMPORTED_MODULE_16__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _mutable_type__WEBPACK_IMPORTED_MODULE_16__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _octree_node_type__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./octree-node.type */ 31726); /* harmony import */ var _octree_node_type__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_octree_node_type__WEBPACK_IMPORTED_MODULE_17__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _octree_node_type__WEBPACK_IMPORTED_MODULE_17__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _octree_node_type__WEBPACK_IMPORTED_MODULE_17__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _popover_settings_type__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./popover-settings.type */ 97066); /* harmony import */ var _popover_settings_type__WEBPACK_IMPORTED_MODULE_18___default = /*#__PURE__*/__webpack_require__.n(_popover_settings_type__WEBPACK_IMPORTED_MODULE_18__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _popover_settings_type__WEBPACK_IMPORTED_MODULE_18__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _popover_settings_type__WEBPACK_IMPORTED_MODULE_18__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _position_type__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./position.type */ 1152); /* harmony import */ var _position_type__WEBPACK_IMPORTED_MODULE_19___default = /*#__PURE__*/__webpack_require__.n(_position_type__WEBPACK_IMPORTED_MODULE_19__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _position_type__WEBPACK_IMPORTED_MODULE_19__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _position_type__WEBPACK_IMPORTED_MODULE_19__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _position2d_type__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./position2d.type */ 71814); /* harmony import */ var _position2d_type__WEBPACK_IMPORTED_MODULE_20___default = /*#__PURE__*/__webpack_require__.n(_position2d_type__WEBPACK_IMPORTED_MODULE_20__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _position2d_type__WEBPACK_IMPORTED_MODULE_20__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _position2d_type__WEBPACK_IMPORTED_MODULE_20__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _quaternion_type__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./quaternion.type */ 91021); /* harmony import */ var _quaternion_type__WEBPACK_IMPORTED_MODULE_21___default = /*#__PURE__*/__webpack_require__.n(_quaternion_type__WEBPACK_IMPORTED_MODULE_21__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _quaternion_type__WEBPACK_IMPORTED_MODULE_21__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _quaternion_type__WEBPACK_IMPORTED_MODULE_21__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _ray_type__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./ray.type */ 55169); /* harmony import */ var _ray_type__WEBPACK_IMPORTED_MODULE_22___default = /*#__PURE__*/__webpack_require__.n(_ray_type__WEBPACK_IMPORTED_MODULE_22__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _ray_type__WEBPACK_IMPORTED_MODULE_22__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _ray_type__WEBPACK_IMPORTED_MODULE_22__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _slab_plane_type__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./slab-plane.type */ 40464); /* harmony import */ var _slab_plane_type__WEBPACK_IMPORTED_MODULE_23___default = /*#__PURE__*/__webpack_require__.n(_slab_plane_type__WEBPACK_IMPORTED_MODULE_23__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _slab_plane_type__WEBPACK_IMPORTED_MODULE_23__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _slab_plane_type__WEBPACK_IMPORTED_MODULE_23__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _quaternion_type__WEBPACK_IMPORTED_MODULE_21__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _quaternion_type__WEBPACK_IMPORTED_MODULE_21__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _token_response_type__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./token-response.type */ 51684); /* harmony import */ var _token_response_type__WEBPACK_IMPORTED_MODULE_24___default = /*#__PURE__*/__webpack_require__.n(_token_response_type__WEBPACK_IMPORTED_MODULE_24__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _token_response_type__WEBPACK_IMPORTED_MODULE_24__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _token_response_type__WEBPACK_IMPORTED_MODULE_24__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _tool_configuration_type__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./tool-configuration.type */ 71462); /* harmony import */ var _tool_configuration_type__WEBPACK_IMPORTED_MODULE_25___default = /*#__PURE__*/__webpack_require__.n(_tool_configuration_type__WEBPACK_IMPORTED_MODULE_25__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _tool_configuration_type__WEBPACK_IMPORTED_MODULE_25__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _tool_configuration_type__WEBPACK_IMPORTED_MODULE_25__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _user_type__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./user.type */ 88184); /* harmony import */ var _user_type__WEBPACK_IMPORTED_MODULE_26___default = /*#__PURE__*/__webpack_require__.n(_user_type__WEBPACK_IMPORTED_MODULE_26__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _user_type__WEBPACK_IMPORTED_MODULE_26__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _user_type__WEBPACK_IMPORTED_MODULE_26__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _viewport_type__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./viewport.type */ 4319); /* harmony import */ var _viewport_type__WEBPACK_IMPORTED_MODULE_27___default = /*#__PURE__*/__webpack_require__.n(_viewport_type__WEBPACK_IMPORTED_MODULE_27__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _viewport_type__WEBPACK_IMPORTED_MODULE_27__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _viewport_type__WEBPACK_IMPORTED_MODULE_27__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _volume_rendering_option_types__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./volume-rendering-option.types */ 98287); /* harmony import */ var _volume_rendering_option_types__WEBPACK_IMPORTED_MODULE_28___default = /*#__PURE__*/__webpack_require__.n(_volume_rendering_option_types__WEBPACK_IMPORTED_MODULE_28__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _volume_rendering_option_types__WEBPACK_IMPORTED_MODULE_28__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _volume_rendering_option_types__WEBPACK_IMPORTED_MODULE_28__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _dicom_naturalized_data_set_type__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./dicom-naturalized-data-set.type */ 7629); /* harmony import */ var _dicom_naturalized_data_set_type__WEBPACK_IMPORTED_MODULE_29___default = /*#__PURE__*/__webpack_require__.n(_dicom_naturalized_data_set_type__WEBPACK_IMPORTED_MODULE_29__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _dicom_naturalized_data_set_type__WEBPACK_IMPORTED_MODULE_29__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _dicom_naturalized_data_set_type__WEBPACK_IMPORTED_MODULE_29__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _dicom_importer_row_type__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./dicom-importer-row.type */ 58513); /* harmony import */ var _dicom_importer_row_type__WEBPACK_IMPORTED_MODULE_30___default = /*#__PURE__*/__webpack_require__.n(_dicom_importer_row_type__WEBPACK_IMPORTED_MODULE_30__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _dicom_importer_row_type__WEBPACK_IMPORTED_MODULE_30__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _dicom_importer_row_type__WEBPACK_IMPORTED_MODULE_30__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /* harmony import */ var _object3d_dialog_config_type__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./object3d-dialog-config.type */ 23009); /* harmony import */ var _object3d_dialog_config_type__WEBPACK_IMPORTED_MODULE_31___default = /*#__PURE__*/__webpack_require__.n(_object3d_dialog_config_type__WEBPACK_IMPORTED_MODULE_31__); /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {}; /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _object3d_dialog_config_type__WEBPACK_IMPORTED_MODULE_31__) if(["default","getTagValue"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _object3d_dialog_config_type__WEBPACK_IMPORTED_MODULE_31__[__WEBPACK_IMPORT_KEY__] /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__); /***/ }, /***/ 61197 /*!***********************************************************!*\ !*** ./libs/types/src/lib/types/interaction-mode.type.ts ***! \***********************************************************/ () { /***/ }, /***/ 69553 /*!******************************************************!*\ !*** ./libs/types/src/lib/types/measurement.type.ts ***! \******************************************************/ () { /***/ }, /***/ 32727 /*!**************************************************!*\ !*** ./libs/types/src/lib/types/mutable.type.ts ***! \**************************************************/ () { /***/ }, /***/ 23009 /*!*****************************************************************!*\ !*** ./libs/types/src/lib/types/object3d-dialog-config.type.ts ***! \*****************************************************************/ () { /***/ }, /***/ 98088 /*!************************************************************!*\ !*** ./libs/types/src/lib/types/object3d-geometry.type.ts ***! \************************************************************/ () { /***/ }, /***/ 31726 /*!******************************************************!*\ !*** ./libs/types/src/lib/types/octree-node.type.ts ***! \******************************************************/ () { /***/ }, /***/ 97066 /*!***********************************************************!*\ !*** ./libs/types/src/lib/types/popover-settings.type.ts ***! \***********************************************************/ () { /***/ }, /***/ 1152 /*!***************************************************!*\ !*** ./libs/types/src/lib/types/position.type.ts ***! \***************************************************/ () { /***/ }, /***/ 71814 /*!*****************************************************!*\ !*** ./libs/types/src/lib/types/position2d.type.ts ***! \*****************************************************/ () { /***/ }, /***/ 91021 /*!*****************************************************!*\ !*** ./libs/types/src/lib/types/quaternion.type.ts ***! \*****************************************************/ () { /***/ }, /***/ 55169 /*!**********************************************!*\ !*** ./libs/types/src/lib/types/ray.type.ts ***! \**********************************************/ () { /***/ }, /***/ 40464 /*!*****************************************************!*\ !*** ./libs/types/src/lib/types/slab-plane.type.ts ***! \*****************************************************/ () { /***/ }, /***/ 51684 /*!*********************************************************!*\ !*** ./libs/types/src/lib/types/token-response.type.ts ***! \*********************************************************/ () { /***/ }, /***/ 71462 /*!*************************************************************!*\ !*** ./libs/types/src/lib/types/tool-configuration.type.ts ***! \*************************************************************/ () { /***/ }, /***/ 88184 /*!***********************************************!*\ !*** ./libs/types/src/lib/types/user.type.ts ***! \***********************************************/ () { /***/ }, /***/ 4319 /*!***************************************************!*\ !*** ./libs/types/src/lib/types/viewport.type.ts ***! \***************************************************/ () { /***/ }, /***/ 98287 /*!*******************************************************************!*\ !*** ./libs/types/src/lib/types/volume-rendering-option.types.ts ***! \*******************************************************************/ () { /***/ }, /***/ 79048 /*!******************************!*\ !*** ./libs/ui/src/index.ts ***! \******************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CancelClickDirective: () => (/* reexport safe */ _lib_directives_cancel_click_directive__WEBPACK_IMPORTED_MODULE_3__.CancelClickDirective), /* harmony export */ CornerSlidersComponent: () => (/* reexport safe */ _lib_corner_sliders_corner_sliders_component__WEBPACK_IMPORTED_MODULE_0__.CornerSlidersComponent), /* harmony export */ DicomImagePreviewComponent: () => (/* reexport safe */ _lib_dicom_image_preview_dicom_image_preview_component__WEBPACK_IMPORTED_MODULE_1__.DicomImagePreviewComponent), /* harmony export */ DicomStackViewerComponent: () => (/* reexport safe */ _lib_dicom_stack_viewer_dicom_stack_viewer_component__WEBPACK_IMPORTED_MODULE_2__.DicomStackViewerComponent), /* harmony export */ DrawerComponent: () => (/* reexport safe */ _lib_drawer_drawer_component__WEBPACK_IMPORTED_MODULE_5__.DrawerComponent), /* harmony export */ EllipsisTipDirective: () => (/* reexport safe */ _lib_directives_ellipsis_tip_directive__WEBPACK_IMPORTED_MODULE_4__.EllipsisTipDirective), /* harmony export */ FileSizePipe: () => (/* reexport safe */ _lib_pipes_file_size_pipe__WEBPACK_IMPORTED_MODULE_8__.FileSizePipe), /* harmony export */ HeadingAreaComponent: () => (/* reexport safe */ _lib_heading_area_heading_area_component__WEBPACK_IMPORTED_MODULE_25__.HeadingAreaComponent), /* harmony export */ IconComponent: () => (/* reexport safe */ _lib_icon_icon_component__WEBPACK_IMPORTED_MODULE_6__.IconComponent), /* harmony export */ MenuItemComponent: () => (/* reexport safe */ _lib_menu_item_menu_item_component__WEBPACK_IMPORTED_MODULE_7__.MenuItemComponent), /* harmony export */ PRIMENG_DEFAULT_SORT_ORDER: () => (/* reexport safe */ _lib_table_table_constants__WEBPACK_IMPORTED_MODULE_17__.PRIMENG_DEFAULT_SORT_ORDER), /* harmony export */ RenameDialogComponent: () => (/* reexport safe */ _lib_rename_dialog_rename_dialog_component__WEBPACK_IMPORTED_MODULE_9__.RenameDialogComponent), /* harmony export */ RowMenuController: () => (/* reexport safe */ _lib_row_menu_row_menu_controller__WEBPACK_IMPORTED_MODULE_10__.RowMenuController), /* harmony export */ SCurveGraphBaseComponent: () => (/* reexport safe */ _lib_s_curve_graph_base_s_curve_graph_base_component__WEBPACK_IMPORTED_MODULE_11__.SCurveGraphBaseComponent), /* harmony export */ ScrollToActiveDirective: () => (/* reexport safe */ _lib_scroll_to_active_scroll_to_active_directive__WEBPACK_IMPORTED_MODULE_12__.ScrollToActiveDirective), /* harmony export */ SectionButtonComponent: () => (/* reexport safe */ _lib_section_button_section_button_component__WEBPACK_IMPORTED_MODULE_13__.SectionButtonComponent), /* harmony export */ SettingsPopoverComponent: () => (/* reexport safe */ _lib_settings_popover_settings_popover_component__WEBPACK_IMPORTED_MODULE_14__.SettingsPopoverComponent), /* harmony export */ SliderComponent: () => (/* reexport safe */ _lib_slider_slider_component__WEBPACK_IMPORTED_MODULE_15__.SliderComponent), /* harmony export */ TableComponent: () => (/* reexport safe */ _lib_table_table_component__WEBPACK_IMPORTED_MODULE_16__.TableComponent), /* harmony export */ ToolbarComponent: () => (/* reexport safe */ _lib_toolbar_toolbar_component__WEBPACK_IMPORTED_MODULE_18__.ToolbarComponent), /* harmony export */ UiSvgIcon: () => (/* reexport safe */ _lib_icon_icon_component__WEBPACK_IMPORTED_MODULE_6__.UiSvgIcon), /* harmony export */ ViewportButtonComponent: () => (/* reexport safe */ _lib_viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_19__.ViewportButtonComponent), /* harmony export */ ViewportIndicatorComponent: () => (/* reexport safe */ _lib_viewport_indicator_viewport_indicator_component__WEBPACK_IMPORTED_MODULE_20__.ViewportIndicatorComponent), /* harmony export */ ViewportLayoutManagerComponent: () => (/* reexport safe */ _lib_viewport_layout_manager_viewport_layout_manager_component__WEBPACK_IMPORTED_MODULE_21__.ViewportLayoutManagerComponent), /* harmony export */ ViewportSettingSliderComponent: () => (/* reexport safe */ _lib_viewport_setting_slider_viewport_setting_slider_component__WEBPACK_IMPORTED_MODULE_22__.ViewportSettingSliderComponent), /* harmony export */ VolumeViewportComponent: () => (/* reexport safe */ _lib_volume_viewport_volume_viewport_component__WEBPACK_IMPORTED_MODULE_23__.VolumeViewportComponent), /* harmony export */ WorkSessionTabComponent: () => (/* reexport safe */ _lib_work_session_tab_work_session_tab_component__WEBPACK_IMPORTED_MODULE_24__.WorkSessionTabComponent), /* harmony export */ annotationHexColors: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.annotationHexColors), /* harmony export */ annotationPaletteHexColors: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.annotationPaletteHexColors), /* harmony export */ appColorTokens: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.appColorTokens), /* harmony export */ appScaleTokens: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.appScaleTokens), /* harmony export */ dangerMenuItem: () => (/* reexport safe */ _lib_theme_menu_item_classes__WEBPACK_IMPORTED_MODULE_26__.dangerMenuItem), /* harmony export */ fullPickerPaletteHexColors: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.fullPickerPaletteHexColors), /* harmony export */ pickerPaletteHexColors: () => (/* reexport safe */ _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__.pickerPaletteHexColors), /* harmony export */ provideUI: () => (/* reexport safe */ _lib_theme_provide_ui__WEBPACK_IMPORTED_MODULE_27__.provideUI) /* harmony export */ }); /* harmony import */ var _lib_corner_sliders_corner_sliders_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/corner-sliders/corner-sliders.component */ 59092); /* harmony import */ var _lib_dicom_image_preview_dicom_image_preview_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/dicom-image-preview/dicom-image-preview.component */ 8410); /* harmony import */ var _lib_dicom_stack_viewer_dicom_stack_viewer_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/dicom-stack-viewer/dicom-stack-viewer.component */ 34184); /* harmony import */ var _lib_directives_cancel_click_directive__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/directives/cancel-click.directive */ 91095); /* harmony import */ var _lib_directives_ellipsis_tip_directive__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/directives/ellipsis-tip.directive */ 49739); /* harmony import */ var _lib_drawer_drawer_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/drawer/drawer.component */ 27018); /* harmony import */ var _lib_icon_icon_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/icon/icon.component */ 92242); /* harmony import */ var _lib_menu_item_menu_item_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/menu-item/menu-item.component */ 94222); /* harmony import */ var _lib_pipes_file_size_pipe__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/pipes/file-size.pipe */ 13698); /* harmony import */ var _lib_rename_dialog_rename_dialog_component__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/rename-dialog/rename-dialog.component */ 98906); /* harmony import */ var _lib_row_menu_row_menu_controller__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/row-menu/row-menu.controller */ 5087); /* harmony import */ var _lib_s_curve_graph_base_s_curve_graph_base_component__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/s-curve-graph-base/s-curve-graph-base.component */ 27608); /* harmony import */ var _lib_scroll_to_active_scroll_to_active_directive__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./lib/scroll-to-active/scroll-to-active.directive */ 55806); /* harmony import */ var _lib_section_button_section_button_component__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./lib/section-button/section-button.component */ 27620); /* harmony import */ var _lib_settings_popover_settings_popover_component__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/settings-popover/settings-popover.component */ 10458); /* harmony import */ var _lib_slider_slider_component__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./lib/slider/slider.component */ 80922); /* harmony import */ var _lib_table_table_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./lib/table/table.component */ 93742); /* harmony import */ var _lib_table_table_constants__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./lib/table/table.constants */ 94644); /* harmony import */ var _lib_toolbar_toolbar_component__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./lib/toolbar/toolbar.component */ 97850); /* harmony import */ var _lib_viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./lib/viewport-button/viewport-button.component */ 14486); /* harmony import */ var _lib_viewport_indicator_viewport_indicator_component__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./lib/viewport-indicator/viewport-indicator.component */ 89416); /* harmony import */ var _lib_viewport_layout_manager_viewport_layout_manager_component__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./lib/viewport-layout-manager/viewport-layout-manager.component */ 55610); /* harmony import */ var _lib_viewport_setting_slider_viewport_setting_slider_component__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./lib/viewport-setting-slider/viewport-setting-slider.component */ 346); /* harmony import */ var _lib_volume_viewport_volume_viewport_component__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./lib/volume-viewport/volume-viewport.component */ 76042); /* harmony import */ var _lib_work_session_tab_work_session_tab_component__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./lib/work-session-tab/work-session-tab.component */ 41216); /* harmony import */ var _lib_heading_area_heading_area_component__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./lib/heading-area/heading-area.component */ 10560); /* harmony import */ var _lib_theme_menu_item_classes__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./lib/theme/menu-item-classes */ 3730); /* harmony import */ var _lib_theme_provide_ui__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./lib/theme/provide-ui */ 57414); /* harmony import */ var _lib_theme_app_tokens__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./lib/theme/app-tokens */ 29904); // COMPONENTS // THEME /***/ }, /***/ 59092 /*!********************************************************************!*\ !*** ./libs/ui/src/lib/corner-sliders/corner-sliders.component.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CornerSlidersComponent: () => (/* binding */ CornerSlidersComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_slider__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/slider */ 31486); /* harmony import */ var _slider_slider_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../slider/slider.component */ 80922); /* harmony import */ var _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../viewport-button/viewport-button.component */ 14486); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); class CornerSlidersComponent { hSliderType = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "hSliderType" }] : [])); vSliderType = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "vSliderType" }] : [])); cSliderStep = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "cSliderStep" }] : [])); hMaxValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "hMaxValue" }] : [])); hMinValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "hMinValue" }] : [])); vMaxValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "vMaxValue" }] : [])); vMinValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "vMinValue" }] : [])); hStartingValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "hStartingValue" }] : [])); vStartingValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "vStartingValue" }] : [])); vSliderValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(this.vStartingValue(), ...(ngDevMode ? [{ debugName: "vSliderValue" }] : [])); hSliderValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(this.hStartingValue(), ...(ngDevMode ? [{ debugName: "hSliderValue" }] : [])); hSliderClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('pointer-events-auto w-39', ...(ngDevMode ? [{ debugName: "hSliderClass" }] : [])); vSliderClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('pointer-events-auto h-39', ...(ngDevMode ? [{ debugName: "vSliderClass" }] : [])); globalClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('grid justify-end border-0 shadow-none outline-none', ...(ngDevMode ? [{ debugName: "globalClass" }] : [])); isDarkMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(true, { ...(ngDevMode ? { debugName: "isDarkMode" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_0__.booleanAttribute }); vSliderChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); hSliderChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); didReset = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); toolTipValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('Reset', ...(ngDevMode ? [{ debugName: "toolTipValue" }] : [])); iconClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('text-xl', ...(ngDevMode ? [{ debugName: "iconClass" }] : [])); onVSliderChange(event_) { this.vSliderValue.set(event_); this.vSliderChanged.emit(event_); } onHSliderChange(event_) { this.hSliderValue.set(event_); this.hSliderChanged.emit(event_); } onReset() { this.didReset.emit(true); } static ɵfac = function CornerSlidersComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CornerSlidersComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: CornerSlidersComponent, selectors: [["lib-corner-sliders"]], inputs: { hSliderType: [1, "hSliderType"], vSliderType: [1, "vSliderType"], cSliderStep: [1, "cSliderStep"], hMaxValue: [1, "hMaxValue"], hMinValue: [1, "hMinValue"], vMaxValue: [1, "vMaxValue"], vMinValue: [1, "vMinValue"], hStartingValue: [1, "hStartingValue"], vStartingValue: [1, "vStartingValue"], vSliderValue: [1, "vSliderValue"], hSliderValue: [1, "hSliderValue"], hSliderClass: [1, "hSliderClass"], vSliderClass: [1, "vSliderClass"], globalClass: [1, "globalClass"], isDarkMode: [1, "isDarkMode"], toolTipValue: [1, "toolTipValue"], iconClass: [1, "iconClass"] }, outputs: { vSliderValue: "vSliderValueChange", hSliderValue: "hSliderValueChange", vSliderChanged: "vSliderChanged", hSliderChanged: "hSliderChanged", didReset: "didReset" }, decls: 6, vars: 19, consts: [[1, "flex", "gap-4", "pt-1", "pr-1.5", "pb-5"], ["name", "h-slider", "sliderOrientation", "horizontal", 3, "sliderChanged", "sliderClassName", "sliderType", "sliderStep", "startingValue", "sliderMin", "sliderMax", "sliderValue"], ["tooltipPosition", "left", "icon", "refresh", 1, "pointer-events-auto", 3, "click", "tooltip", "ariaLabel", "iconClass"], [1, "flex", "w-[91%]", "justify-end"], ["name", "v-slider", "sliderOrientation", "vertical", 3, "sliderChanged", "sliderClassName", "sliderType", "sliderValue", "sliderStep", "startingValue", "sliderMin", "sliderMax"]], template: function CornerSlidersComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "div")(1, "div", 0)(2, "lib-slider", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("sliderChanged", function CornerSlidersComponent_Template_lib_slider_sliderChanged_2_listener($event) { return ctx.onHSliderChange($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](3, "lib-viewport-button", 2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("click", function CornerSlidersComponent_Template_lib_viewport_button_click_3_listener() { return ctx.onReset(); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](4, "div", 3)(5, "lib-slider", 4); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("sliderChanged", function CornerSlidersComponent_Template_lib_slider_sliderChanged_5_listener($event) { return ctx.onVSliderChange($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"](ctx.globalClass()); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("sliderClassName", ctx.hSliderClass())("sliderType", ctx.hSliderType())("sliderStep", ctx.cSliderStep())("startingValue", ctx.hStartingValue())("sliderMin", ctx.hMinValue())("sliderMax", ctx.hMaxValue())("sliderValue", ctx.hSliderValue()); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("tooltip", ctx.toolTipValue())("ariaLabel", ctx.toolTipValue())("iconClass", ctx.iconClass()); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("sliderClassName", ctx.vSliderClass())("sliderType", ctx.vSliderType())("sliderValue", ctx.vSliderValue())("sliderStep", ctx.cSliderStep())("startingValue", ctx.vStartingValue())("sliderMin", ctx.vMinValue())("sliderMax", ctx.vMaxValue()); } }, dependencies: [primeng_slider__WEBPACK_IMPORTED_MODULE_2__.SliderModule, _angular_forms__WEBPACK_IMPORTED_MODULE_1__.FormsModule, _slider_slider_component__WEBPACK_IMPORTED_MODULE_3__.SliderComponent, _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_4__.ViewportButtonComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 8410 /*!******************************************************************************!*\ !*** ./libs/ui/src/lib/dicom-image-preview/dicom-image-preview.component.ts ***! \******************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomImagePreviewComponent: () => (/* binding */ DicomImagePreviewComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); function DicomImagePreviewComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdomElement"](0, "img", 1); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdomProperty"]("src", ctx_r0.config.data.imageUrl, _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵsanitizeUrl"]); } } class DicomImagePreviewComponent { config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_1__.DynamicDialogConfig); static ɵfac = function DicomImagePreviewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomImagePreviewComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineComponent"]({ type: DicomImagePreviewComponent, selectors: [["lib-dicom-image-preview"]], decls: 2, vars: 1, consts: [[1, "flex", "items-center", "justify-center", "py-2"], ["alt", "DICOM Preview", 1, "h-auto", "max-w-full", "shadow-lg", 3, "src"]], template: function DicomImagePreviewComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdomElementStart"](0, "div", 0); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵconditionalCreate"](1, DicomImagePreviewComponent_Conditional_1_Template, 1, 1, "img", 1); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵconditional"](ctx.config.data.imageUrl ? 1 : -1); } }, encapsulation: 2 }); } /***/ }, /***/ 34184 /*!****************************************************************************!*\ !*** ./libs/ui/src/lib/dicom-stack-viewer/dicom-stack-viewer.component.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomStackViewerComponent: () => (/* binding */ DicomStackViewerComponent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 14566); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @cornerstonejs/core */ 70611); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @cornerstonejs/core */ 19401); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @cornerstonejs/core */ 10372); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @cornerstonejs/core */ 63600); /* harmony import */ var _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @cornerstonejs/core/enums */ 43089); /* harmony import */ var _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @cornerstonejs/core/enums */ 80600); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @cornerstonejs/tools */ 1773); /* harmony import */ var _cornerstonejs_tools_enums__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @cornerstonejs/tools/enums */ 64543); /* harmony import */ var _tomoverse_data_access__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/data-access */ 42541); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["viewportEl"]; class DicomStackViewerComponent { cornerstoneInit = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.CornerstoneInitService); volumeLoaderService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_tomoverse_data_access__WEBPACK_IMPORTED_MODULE_13__.VolumeLoaderService); destroyRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.DestroyRef); seriesUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "seriesUid" }] : [])); studyUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "studyUid" }] : [])); storeUid = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "storeUid" }] : [])); sliceIndex = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "sliceIndex" }] : [])); sliceIndexChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); totalInstanceImages = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); static ENGINE_ID = `dicom-stack-viewer-engine`; static VIEWPORT_ID = 'dicom-stack-viewer-viewport'; static TOOL_GROUP_ID = `dicom-stack-viewer-tool-group-${DicomStackViewerComponent.ENGINE_ID}`; viewportEl = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('viewportEl'); engine; viewInitialized = false; abortController; currentVolumeId; lastSetIndex = undefined; volumeNewImageListener = undefined; constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const studyUid = this.studyUid(); const seriesUid = this.seriesUid(); if (this.viewInitialized && studyUid && seriesUid) { this.loadVolume(studyUid, seriesUid); } }); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const index = this.sliceIndex(); if (this.viewInitialized && index !== null && index !== undefined && this.engine) { this.jumpToSlice(index); } }); this.destroyRef.onDestroy(() => this.cleanup()); } ngAfterViewInit() { this.cornerstoneInit.ensureInitialized().then(() => this.volumeLoaderService.init()).then(() => { this.initEngine(); this.addVolumeListeners(); this.viewInitialized = true; const studyUid = this.studyUid(); const seriesUid = this.seriesUid(); if (studyUid && seriesUid) { this.loadVolume(studyUid, seriesUid); } }); } ngOnDestroy() { this.cleanup(); } initEngine() { this.engine = new _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__["default"](DicomStackViewerComponent.ENGINE_ID); this.engine.enableElement({ defaultOptions: { orientation: _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_10__["default"].AXIAL }, element: this.viewportEl().nativeElement, type: _cornerstonejs_core_enums__WEBPACK_IMPORTED_MODULE_9__["default"].ORTHOGRAPHIC, viewportId: DicomStackViewerComponent.VIEWPORT_ID }); this.engine.resize(true, true); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.registerCornerstoneTools)([_cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_11__["default"]]); (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.registerToolGroupForViewports)(DicomStackViewerComponent.TOOL_GROUP_ID, [DicomStackViewerComponent.VIEWPORT_ID], DicomStackViewerComponent.ENGINE_ID, [{ name: _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_11__["default"].toolName, toolBinding: { bindings: [{ mouseButton: _cornerstonejs_tools_enums__WEBPACK_IMPORTED_MODULE_12__.MouseBindings.Wheel }, { mouseButton: _cornerstonejs_tools_enums__WEBPACK_IMPORTED_MODULE_12__.MouseBindings.Primary }] } }]); } /** * Preview the first phase only: a multiphase series' interleaved positions can't form one 3D * grid, so a volume built from every phase renders grey. */ resolvePreviewImageIds(studyUid, seriesUid, storeUid) { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const phases = yield _this.volumeLoaderService.ensureSeriesPhases(studyUid, seriesUid, storeUid); return phases[0]?.imageIds ?? []; })(); } loadVolume(studyUid, seriesUid) { var _this2 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { _this2.abortController?.abort(); _this2.abortController = new AbortController(); const { signal } = _this2.abortController; const storeUid = _this2.storeUid(); if (!_this2.engine || !storeUid) return; try { const imageIds = yield _this2.resolvePreviewImageIds(studyUid, seriesUid, storeUid); _this2.totalInstanceImages.emit(imageIds.length); if (signal.aborted) return; const volumeId = `${_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.TOMOVERSE_IMAGE_VOLUME_SCHEME}:preview-${studyUid}-${seriesUid}`; _this2.clearVolume(volumeId); const volume = yield _this2.getVolume(volumeId, imageIds); if (signal.aborted) return; volume.load(() => { /* no-op progress callback */ }); yield _this2.renderVolumeInViewport(volumeId, signal); } catch (error) { if (!signal.aborted) { console.error('failed to load volume', error); } } })(); } clearVolume(volumeId) { if (this.currentVolumeId && this.currentVolumeId !== volumeId) { try { _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"].removeVolumeLoadObject(this.currentVolumeId); } catch { console.warn('failed to clear previous volume from cache'); } } this.currentVolumeId = volumeId; } getVolume(volumeId, imageIds) { return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { return _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_6__["default"].getVolume(volumeId) ?? (yield _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_7__.createAndCacheVolume(volumeId, { imageIds })); })(); } renderVolumeInViewport(volumeId, signal) { var _this3 = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { const viewport = _this3.engine?.getViewport(DicomStackViewerComponent.VIEWPORT_ID); if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__["default"])) return; yield viewport.setVolumes([{ volumeId }]); if (signal.aborted) return; const { level, width } = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.DEFAULT_WINDOW_PRESET; viewport.setProperties({ voiRange: { lower: level - width / 2, upper: level + width / 2 } }); _this3.engine?.resize(true, true); viewport.resetCamera(); viewport.render(); })(); } addVolumeListeners() { const element = this.viewportEl().nativeElement; this.volumeNewImageListener = event => { const { imageIndex } = event.detail; this.sliceIndexChange.emit(imageIndex); }; element.addEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].VOLUME_NEW_IMAGE, this.volumeNewImageListener); } jumpToSlice(index) { if (!this.engine || !this.currentVolumeId || this.lastSetIndex === index) return; this.lastSetIndex = index; const viewport = this.engine.getViewport(DicomStackViewerComponent.VIEWPORT_ID); _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_8__.jumpToSlice(viewport.element, { imageIndex: index }); viewport.render(); } cleanup() { this.abortController?.abort(); if (this.volumeNewImageListener) { this.viewportEl().nativeElement.removeEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].VOLUME_NEW_IMAGE, this.volumeNewImageListener); this.volumeNewImageListener = undefined; } this.engine?.disableElement(DicomStackViewerComponent.VIEWPORT_ID); this.engine?.destroy(); this.engine = undefined; } static ɵfac = function DicomStackViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomStackViewerComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdefineComponent"]({ type: DicomStackViewerComponent, selectors: [["lib-dicom-stack-viewer"]], viewQuery: function DicomStackViewerComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵviewQuerySignal"](ctx.viewportEl, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵqueryAdvance"](); } }, inputs: { seriesUid: [1, "seriesUid"], studyUid: [1, "studyUid"], storeUid: [1, "storeUid"], sliceIndex: [1, "sliceIndex"] }, outputs: { sliceIndexChange: "sliceIndexChange", totalInstanceImages: "totalInstanceImages" }, decls: 2, vars: 0, consts: [["viewportEl", ""], [1, "h-full", "w-full", "cursor-default!"]], template: function DicomStackViewerComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_15__["ɵɵdomElement"](0, "div", 1, 0); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 91095 /*!**************************************************************!*\ !*** ./libs/ui/src/lib/directives/cancel-click.directive.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CancelClickDirective: () => (/* binding */ CancelClickDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); /** * Because `p-accordion-header` has a host-level click handler we can't * overwrite, we attach this directive which intercepts the event early. * We only let the actual event propagate when it comes from the desired elements, * otherwise we run them through a `filteredEvents` output to be used differently. */ class CancelClickDirective { el = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.ElementRef); filteredClick = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); constructor() { const listener = this.onClick.bind(this); this.el.nativeElement.addEventListener('click', listener, true); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => { this.el.nativeElement.removeEventListener('click', listener, true); }); } onClick(event) { // Only propagate the event if the an allowed element was clicked if (event.target.closest('[data-propagate-click]')) { return; } event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); this.filteredClick.emit(event); } static ɵfac = function CancelClickDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CancelClickDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineDirective"]({ type: CancelClickDirective, selectors: [["", "libCancelClick", ""]], outputs: { filteredClick: "filteredClick" } }); } /***/ }, /***/ 49739 /*!**************************************************************!*\ !*** ./libs/ui/src/lib/directives/ellipsis-tip.directive.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EllipsisTipDirective: () => (/* binding */ EllipsisTipDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); /** * Clips the host's content to one line with an ellipsis and reports whether it is actually truncated. */ class EllipsisTipDirective { el = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef).nativeElement; resizeObserver = new ResizeObserver(() => this.check()); truncated = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(false, ...(ngDevMode ? [{ debugName: "truncated" }] : [])); ngAfterViewInit() { this.resizeObserver.observe(this.el); this.check(); } ngOnDestroy() { this.resizeObserver.disconnect(); } check() { this.truncated.set(this.el.scrollWidth > this.el.clientWidth); } static ɵfac = function EllipsisTipDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EllipsisTipDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ type: EllipsisTipDirective, selectors: [["", "libEllipsisTip", ""]], hostAttrs: [1, "truncate-cell"], hostBindings: function EllipsisTipDirective_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("mouseenter", function EllipsisTipDirective_mouseenter_HostBindingHandler() { return ctx.check(); }); } }, exportAs: ["libEllipsisTip"] }); } /***/ }, /***/ 69458 /*!*****************************************************************!*\ !*** ./libs/ui/src/lib/drawer/drawer-context-menu.directive.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DrawerContextMenuDirective: () => (/* binding */ DrawerContextMenuDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 14975); class DrawerContextMenuDirective { menu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "menu" }] : [])); onContextMenu(event) { const menu = this.menu(); if (!menu) return; const menuModel = typeof menu.model === 'function' ? menu.model() : menu.model; if (!menuModel?.length) { console.warn('Menu model is empty or not yet initialized'); return; } event.preventDefault(); event.stopPropagation(); menu.show(event); } static ɵfac = function DrawerContextMenuDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DrawerContextMenuDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ type: DrawerContextMenuDirective, selectors: [["", "libDrawerContextMenu", ""]], hostBindings: function DrawerContextMenuDirective_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵlistener"]("contextmenu", function DrawerContextMenuDirective_contextmenu_HostBindingHandler($event) { return ctx.onContextMenu($event); }); } }, inputs: { menu: [1, "menu"] } }); } /***/ }, /***/ 27018 /*!****************************************************!*\ !*** ./libs/ui/src/lib/drawer/drawer.component.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DrawerComponent: () => (/* binding */ DrawerComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/contextmenu */ 94635); /* harmony import */ var primeng_drawer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/drawer */ 17738); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _drawer_context_menu_directive__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./drawer-context-menu.directive */ 69458); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/api */ 62751); const _c0 = ["*", [["", "drawerMenu", ""]], [["", "headerActions", ""]]]; const _c1 = ["*", "[drawerMenu]", "[headerActions]"]; function DrawerComponent_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 4)(1, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojection"](3, 2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("menu", ctx_r0.projectedContextMenu()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](ctx_r0.header()); } } const defaultMotionOptions = { duration: 150 }; class DrawerComponent { drawerVisible = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(false, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : [])); appendToTarget = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(document.body, ...(ngDevMode ? [{ debugName: "appendToTarget" }] : [])); header = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "header" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); motionOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "motionOptions" }] : [])); mergedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const pt = this.pt(); return { ...pt, header: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.cn)('h-[46px] py-0 pl-[15px] pr-1 text-sm', pt.header) }; }, ...(ngDevMode ? [{ debugName: "mergedPt" }] : [])); mergedMotionOptions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { return { ...defaultMotionOptions, ...this.motionOptions() }; }, ...(ngDevMode ? [{ debugName: "mergedMotionOptions" }] : [])); projectedContextMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.contentChild)(primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, ...(ngDevMode ? [{ debugName: "projectedContextMenu" }] : [])); closeDrawer() { this.drawerVisible.set(false); } // PrimeNG's p-drawer re-parents its container into `appendToTarget()` via a raw // `appendChild()` the FIRST time it opens (subsequent opens just toggle CSS on the same // node - see `modalVisible`, which is a one-way latch in primeng-drawer.mjs). On Safari, // that first reparent leaves the container with a stale/incorrect box that the enter // motion then visibly animates through (a brief flash of a gap next to the drawer) before // it self-corrects. The enter/leave motion is a CSS `animation` (`.p-drawer-enter-right` // in primeng-drawer.mjs), not a `transition`, so it has to be suppressed via the // `animation` property - skip it just for this first-ever open, forcing the drawer to snap // straight to the correct final state instead. Every later open keeps the normal slide-in. drawerRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)(primeng_drawer__WEBPACK_IMPORTED_MODULE_3__.Drawer, ...(ngDevMode ? [{ debugName: "drawerRef" }] : [])); firstShowHandled = new WeakSet(); handleShown() { // Read the container straight off our own p-drawer instance rather than querying // appendToTarget() for `.p-drawer` - that target can be shared (it defaults to // document.body, and cached routes can leave more than one drawer mounted there), so a // class-based query could grab a different drawer's element. const drawerElement = this.drawerRef()?.container; if (!drawerElement) return; if (this.firstShowHandled.has(drawerElement)) { drawerElement.getBoundingClientRect(); return; } this.firstShowHandled.add(drawerElement); drawerElement.style.animation = 'none'; drawerElement.getBoundingClientRect(); requestAnimationFrame(() => { requestAnimationFrame(() => { drawerElement.style.animation = ''; }); }); } static ɵfac = function DrawerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DrawerComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: DrawerComponent, selectors: [["lib-drawer"]], contentQueries: function DrawerComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵcontentQuerySignal"](dirIndex, ctx.projectedContextMenu, primeng_contextmenu__WEBPACK_IMPORTED_MODULE_2__.ContextMenu, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](); } }, viewQuery: function DrawerComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵviewQuerySignal"](ctx.drawerRef, primeng_drawer__WEBPACK_IMPORTED_MODULE_3__.Drawer, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](); } }, inputs: { drawerVisible: [1, "drawerVisible"], appendToTarget: [1, "appendToTarget"], header: [1, "header"], pt: [1, "pt"], motionOptions: [1, "motionOptions"] }, outputs: { drawerVisible: "drawerVisibleChange" }, ngContentSelectors: _c1, decls: 6, vars: 6, consts: [["modal", "false", "position", "right", 3, "visibleChange", "onShow", "visible", "appendTo", "motionOptions", "closeOnEscape", "pt"], ["pTemplate", "header"], ["libDrawerContextMenu", "", 1, "flex", "h-full", "w-full", "grow", "flex-col", 3, "menu"], [1, "h-full", "overflow-auto", 3, "contextmenu"], ["libDrawerContextMenu", "", 1, "flex", "w-full", "items-center", "justify-between", 3, "menu"]], template: function DrawerComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojectionDef"](_c0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "p-drawer", 0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayListener"]("visibleChange", function DrawerComponent_Template_p_drawer_visibleChange_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayBindingSet"](ctx.drawerVisible, $event) || (ctx.drawerVisible = $event); return $event; }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("onShow", function DrawerComponent_Template_p_drawer_onShow_0_listener() { return ctx.handleShown(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplate"](1, DrawerComponent_ng_template_1_Template, 4, 2, "ng-template", 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](2, "div", 2)(3, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("contextmenu", function DrawerComponent_Template_div_contextmenu_3_listener($event) { return $event.stopPropagation(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojection"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojection"](5, 1, ["#contextMenu", ""]); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtwoWayProperty"]("visible", ctx.drawerVisible); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("appendTo", ctx.appendToTarget())("motionOptions", ctx.mergedMotionOptions())("closeOnEscape", false)("pt", ctx.mergedPt()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("menu", ctx.projectedContextMenu()); } }, dependencies: [primeng_drawer__WEBPACK_IMPORTED_MODULE_3__.DrawerModule, primeng_drawer__WEBPACK_IMPORTED_MODULE_3__.Drawer, primeng_api__WEBPACK_IMPORTED_MODULE_7__.PrimeTemplate, _drawer_context_menu_directive__WEBPACK_IMPORTED_MODULE_5__.DrawerContextMenuDirective], encapsulation: 2 }); } /***/ }, /***/ 10560 /*!****************************************************************!*\ !*** ./libs/ui/src/lib/heading-area/heading-area.component.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ HeadingAreaComponent: () => (/* binding */ HeadingAreaComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/panel */ 22949); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = [[["", "left", ""]], [["", "right", ""]]]; const _c1 = ["[left]", "[right]"]; const _c2 = () => ({ padding: "0.75rem" }); const _c3 = a0 => ({ style: a0 }); const _c4 = a0 => ({ content: a0 }); const _c5 = () => ({}); function HeadingAreaComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "p-button", 4); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("click", function HeadingAreaComponent_Conditional_3_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵresetView"](ctx_r1.onBack()); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](1, "lib-icon", 5); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("ariaLabel", ctx_r1.backAriaLabel()); } } class HeadingAreaComponent { showBackButton = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(true, ...(ngDevMode ? [{ debugName: "showBackButton" }] : [])); backAriaLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "backAriaLabel" }] : [])); back = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); onBack() { this.back.emit(); } static ɵfac = function HeadingAreaComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || HeadingAreaComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: HeadingAreaComponent, selectors: [["lib-heading-area"]], inputs: { showBackButton: [1, "showBackButton"], backAriaLabel: [1, "backAriaLabel"] }, outputs: { back: "back" }, ngContentSelectors: _c1, decls: 7, vars: 9, consts: [[1, "mb-4", 3, "showHeader", "pt"], [1, "flex", "items-center", "justify-between"], [1, "flex", "items-center", "gap-4"], ["data-test-id", "heading-area-p-button-back", "severity", "secondary", "variant", "text", 1, "[&_.p-button]:size-1", "[&_.p-button]:p-[19px]", "[&_.p-button_svg]:size-(--p-app-icon-size-xxs)", 3, "ariaLabel"], ["data-test-id", "heading-area-p-button-back", "severity", "secondary", "variant", "text", 1, "[&_.p-button]:size-1", "[&_.p-button]:p-[19px]", "[&_.p-button_svg]:size-(--p-app-icon-size-xxs)", 3, "click", "ariaLabel"], ["icon", "arrow-left"]], template: function HeadingAreaComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵprojectionDef"](_c0); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "p-panel", 0)(1, "div", 1)(2, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](3, HeadingAreaComponent_Conditional_3_Template, 2, 1, "p-button", 3); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵprojection"](4); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](5, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵprojection"](6, 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("showHeader", false)("pt", !ctx.showBackButton() ? _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpureFunction1"](6, _c4, _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpureFunction1"](4, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpureFunction0"](3, _c2))) : _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵpureFunction0"](8, _c5)); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"](ctx.showBackButton() ? 3 : -1); } }, dependencies: [primeng_panel__WEBPACK_IMPORTED_MODULE_2__.PanelModule, primeng_panel__WEBPACK_IMPORTED_MODULE_2__.Panel, primeng_button__WEBPACK_IMPORTED_MODULE_1__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_1__.Button, _icon_icon_component__WEBPACK_IMPORTED_MODULE_3__.IconComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 92242 /*!************************************************!*\ !*** ./libs/ui/src/lib/icon/icon.component.ts ***! \************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ IconComponent: () => (/* binding */ IconComponent), /* harmony export */ UiSvgIcon: () => (/* binding */ UiSvgIcon) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); function IconComponent_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "img", 3); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleMap"](ctx_r0.mergedMulticolorSvgStyles()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomProperty"]("src", ctx_r0.svgPath(), _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵsanitizeUrl"])("alt", ctx_r0.icon()); } } function IconComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "span", 4); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleMap"](ctx_r0.mergedSvgStyles()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("aria-label", ctx_r0.icon()); } } function IconComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](0, IconComponent_Conditional_0_Conditional_0_Template, 1, 4, "img", 1)(1, IconComponent_Conditional_0_Conditional_1_Template, 1, 3, "span", 2); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx_r0.isMulticolorSvgIcon() ? 0 : 1); } } function IconComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "i"); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstyleMap"](ctx_r0.mergedPrimeStyles()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵclassMap"](ctx_r0.mergedIconClass()); } } var UiSvgIcon; (function (UiSvgIcon) { UiSvgIcon["ALIGN_HORIZONTAL_CENTER"] = "align-horizontal-center"; UiSvgIcon["ANGLE"] = "angle"; UiSvgIcon["ARCHITECTURE"] = "architecture"; UiSvgIcon["CLOSEDSPLINE"] = "closed-spline"; UiSvgIcon["CURVE"] = "curve"; UiSvgIcon["DEVICE"] = "device"; UiSvgIcon["DISTANCE"] = "distance"; UiSvgIcon["DRAG_HANDLE"] = "drag-handle"; UiSvgIcon["FULLSCREEN"] = "fullscreen"; UiSvgIcon["LIBRARY"] = "library"; UiSvgIcon["MAXIMIZE"] = "maximize"; UiSvgIcon["MINIMIZE"] = "minimize"; UiSvgIcon["MODEL"] = "model"; UiSvgIcon["MOUSE_POINTER"] = "mouse-pointer"; UiSvgIcon["OBJECT_3D"] = "object-3d"; UiSvgIcon["OPENSPLINE"] = "open-spline"; UiSvgIcon["PLANAR_REFORMATION"] = "planar-reformation"; UiSvgIcon["POINT"] = "point"; UiSvgIcon["POSTERIOR"] = "posterior"; UiSvgIcon["PROTOCOL"] = "protocol"; UiSvgIcon["REFERENCE_LINES"] = "reference-lines"; UiSvgIcon["RELATIVE_MEASUREMENTS"] = "relative-measurements"; UiSvgIcon["ROTATION_3D"] = "rotation-3d"; UiSvgIcon["RULER"] = "ruler"; UiSvgIcon["SCAN"] = "scan"; UiSvgIcon["SCREEN_ROTATION"] = "screen-rotation"; UiSvgIcon["SCREENSHOT"] = "screenshot"; UiSvgIcon["SCURVE"] = "s-curve"; UiSvgIcon["SEGMENTATION"] = "segmentation"; UiSvgIcon["SETTINGS"] = "settings"; UiSvgIcon["SHARE"] = "share"; UiSvgIcon["SWAP"] = "swap"; UiSvgIcon["TABLE"] = "table"; UiSvgIcon["USER_CIRCLE"] = "user-circle"; })(UiSvgIcon || (UiSvgIcon = {})); // Icons rendered as a currentColor mask. const svgIconNames = new Set(Object.values(UiSvgIcon)); // Icons authored with their own color palette. Rendered as an so the fills survive. const multicolorSvgIconNames = new Set([UiSvgIcon.SEGMENTATION]); const svgBasePath = './assets/svg'; // This app's name for a glyph doesn't always match PrimeIcons' name for it. const primeIconNameOverrides = { 'eye-off': 'eye-slash', target: 'map-marker', typography: 'tag' }; class IconComponent { icon = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "icon" }] : [])); iconClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "iconClass" }] : [])); iconStyle = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)({}, ...(ngDevMode ? [{ debugName: "iconStyle" }] : [])); iconType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('auto', ...(ngDevMode ? [{ debugName: "iconType" }] : [])); hostClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const classes = this.iconClass(); if (this.isSvgIcon()) { return classes ? `keep-bg ${classes}` : 'keep-bg'; } return classes; }, ...(ngDevMode ? [{ debugName: "hostClass" }] : [])); mergedIconClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const name = this.icon(); const primeName = primeIconNameOverrides[name] ?? name; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.cn)(`pi pi-${primeName}`, this.iconClass()); }, ...(ngDevMode ? [{ debugName: "mergedIconClass" }] : [])); isSvgIcon = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const iconType = this.iconType(); if (iconType === 'svg') return true; if (iconType === 'prime') return false; return svgIconNames.has(this.icon()); }, ...(ngDevMode ? [{ debugName: "isSvgIcon" }] : [])); isMulticolorSvgIcon = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => multicolorSvgIconNames.has(this.icon()), ...(ngDevMode ? [{ debugName: "isMulticolorSvgIcon" }] : [])); svgPath = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => `${svgBasePath}/${this.icon()}.svg`, ...(ngDevMode ? [{ debugName: "svgPath" }] : [])); mergedMulticolorSvgStyles = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { return { display: 'block', height: '100%', 'object-fit': 'contain', width: '100%', ...this.iconStyle() }; }, ...(ngDevMode ? [{ debugName: "mergedMulticolorSvgStyles" }] : [])); mergedSvgStyles = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const path = this.svgPath(); return { '-webkit-mask-image': `url('${path}')`, '-webkit-mask-repeat': 'no-repeat', 'background-color': 'currentColor', display: 'block', height: '100%', 'mask-image': `url('${path}')`, 'mask-position': 'center', 'mask-repeat': 'no-repeat', 'mask-size': 'contain', width: '100%', ...this.iconStyle() }; }, ...(ngDevMode ? [{ debugName: "mergedSvgStyles" }] : [])); // PrimeIcons glyphs scale with font-size; `size-*` only sets the box around them. mergedPrimeStyles = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { return { 'align-items': 'center', display: 'flex', 'font-size': 'inherit', 'justify-content': 'center', ...this.iconStyle() }; }, ...(ngDevMode ? [{ debugName: "mergedPrimeStyles" }] : [])); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.cn; static ɵfac = function IconComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || IconComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: IconComponent, selectors: [["lib-icon"]], hostAttrs: [2, "display", "inline-flex", "align-items", "center", "justify-content", "center", "vertical-align", "middle", "flex-shrink", "0", "box-sizing", "content-box"], hostVars: 2, hostBindings: function IconComponent_HostBindings(rf, ctx) { if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵclassMap"](ctx.hostClass()); } }, inputs: { icon: [1, "icon"], iconClass: [1, "iconClass"], iconStyle: [1, "iconStyle"], iconType: [1, "iconType"] }, decls: 2, vars: 1, consts: [[3, "class", "style"], [3, "src", "alt", "style"], ["role", "img", 3, "style"], [3, "src", "alt"], ["role", "img"]], template: function IconComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](0, IconComponent_Conditional_0_Template, 2, 1)(1, IconComponent_Conditional_1_Template, 1, 4, "i", 0); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx.isSvgIcon() ? 0 : 1); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 94222 /*!**********************************************************!*\ !*** ./libs/ui/src/lib/menu-item/menu-item.component.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MenuItemComponent: () => (/* binding */ MenuItemComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var primeng_badge__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/badge */ 73946); /* harmony import */ var primeng_ripple__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/ripple */ 73271); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); function MenuItemComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](0, "lib-icon", 1); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); const icon_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵreadContextLet"](1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("icon", icon_r2)("iconStyle", ctx_r0.item().iconStyle ?? undefined)("iconClass", ctx_r0.cn("p-menu-item-icon", ctx_r0.item().iconClass)); } } function MenuItemComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](0, "lib-icon", 3); } } function MenuItemComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](0, "p-badge", 4); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); const badge_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵreadContextLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("value", badge_r3); } } class MenuItemComponent { item = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "item" }] : [])); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.cn; static ɵfac = function MenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MenuItemComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: MenuItemComponent, selectors: [["lib-menu-item"]], inputs: { item: [1, "item"] }, decls: 9, vars: 11, consts: [["pRipple", "", 1, "flex", "cursor-pointer", "items-center", "gap-2", "px-3", "py-2"], [1, "size-3.5", 3, "icon", "iconStyle", "iconClass"], [1, "flex", "w-full", "justify-between"], ["icon", "angle-right", "iconClass", "p-menu-item-icon ms-auto", 1, "size-3.5"], [1, "ms-auto", 3, "value"]], template: function MenuItemComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "a", 0); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdeclareLet"](1)(2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](3, MenuItemComponent_Conditional_3_Template, 1, 3, "lib-icon", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](4, "span", 2)(5, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](7, MenuItemComponent_Conditional_7_Template, 1, 0, "lib-icon", 3); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditionalCreate"](8, MenuItemComponent_Conditional_8_Template, 1, 1, "p-badge", 4); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"]()(); } if (rf & 2) { let tmp_1_0; let tmp_7_0; _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"](ctx.item().linkClass); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵattribute"]("data-test-id", "menu-item-a-" + ((tmp_1_0 = ctx.item().label) == null ? null : (tmp_1_0 = tmp_1_0.toLowerCase()) == null ? null : tmp_1_0.replaceAll(" ", "-"))); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); const icon_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵstoreLet"](ctx.item().icon); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); const badge_r5 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵstoreLet"](ctx.item().badge); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"](icon_r4 ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵclassMap"](ctx.cn("p-menu-item-label text-sm text-nowrap", ctx.item().labelClass)); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵtextInterpolate1"](" ", ctx.item().label, " "); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"](((tmp_7_0 = ctx.item().items) == null ? null : tmp_7_0.length) ? 7 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵconditional"](badge_r5 ? 8 : -1); } }, dependencies: [_icon_icon_component__WEBPACK_IMPORTED_MODULE_4__.IconComponent, primeng_ripple__WEBPACK_IMPORTED_MODULE_2__.Ripple, primeng_badge__WEBPACK_IMPORTED_MODULE_1__.Badge], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 13698 /*!*************************************************!*\ !*** ./libs/ui/src/lib/pipes/file-size.pipe.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FileSizePipe: () => (/* binding */ FileSizePipe) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 14975); /** Formats a byte count as a human-readable size: `34.33 GB`, `12.40 MB`, `3.1 KB`. */ class FileSizePipe { transform(bytes) { if (bytes === null || bytes === undefined || Number.isNaN(bytes)) return '—'; if (bytes >= 1_073_741_824) return `${(bytes / 1_073_741_824).toFixed(2)} GB`; if (bytes >= 1_048_576) return `${(bytes / 1_048_576).toFixed(2)} MB`; return `${(bytes / 1024).toFixed(1)} KB`; } static ɵfac = function FileSizePipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FileSizePipe)(); }; static ɵpipe = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "libFileSize", type: FileSizePipe, pure: true }); } /***/ }, /***/ 98906 /*!******************************************************************!*\ !*** ./libs/ui/src/lib/rename-dialog/rename-dialog.component.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RenameDialogComponent: () => (/* binding */ RenameDialogComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/dynamicdialog */ 29496); /* harmony import */ var primeng_floatlabel__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/floatlabel */ 95717); /* harmony import */ var primeng_inputtext__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/inputtext */ 670); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../icon/icon.component */ 92242); const _c0 = ["suggestionsPopover"]; const _c1 = ["nameInput"]; const _c2 = ["suggestionButton"]; const _c3 = () => ({ root: "size-6" }); function RenameDialogComponent_For_9_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](0, "li")(1, "button", 15, 2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("mousedown", function RenameDialogComponent_For_9_Template_button_mousedown_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.preventDefault()); })("click", function RenameDialogComponent_For_9_Template_button_click_1_listener($event) { const suggestion_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r3).$implicit; const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnextContext"](); $event.stopPropagation(); $event.preventDefault(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r4.selectNameSuggestion(suggestion_r4)); }); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"]()(); } if (rf & 2) { const suggestion_r4 = ctx.$implicit; const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("pTooltip", ctx_r4.clampedSuggestions().has(suggestion_r4) ? suggestion_r4 : undefined)("tooltipPosition", ctx_r4.clampedSuggestions().has(suggestion_r4) ? "left" : undefined); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtextInterpolate1"](" ", suggestion_r4, " "); } } function RenameDialogComponent_Conditional_12_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelement"](0, "lib-icon", 17); } } function RenameDialogComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](0, "p-button", 16); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipe"](1, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("mousedown", function RenameDialogComponent_Conditional_12_Template_p_button_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.preventDefault()); })("click", function RenameDialogComponent_Conditional_12_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r6); const ctx_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r4.clearName()); }); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtemplate"](3, RenameDialogComponent_Conditional_12_ng_template_3_Template, 1, 0, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("pTooltip", _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipeBind1"](1, 3, "common.clearName"))("ariaLabel", _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpipeBind1"](2, 5, "common.clearName"))("pt", _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵpureFunction0"](7, _c3)); } } class RenameDialogComponent { clampedSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(new Set(), ...(ngDevMode ? [{ debugName: "clampedSuggestions" }] : [])); suggestionsPopover = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)('suggestionsPopover', ...(ngDevMode ? [{ debugName: "suggestionsPopover" }] : [])); filteredNameSuggestions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)([], ...(ngDevMode ? [{ debugName: "filteredNameSuggestions" }] : [])); nameInput = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)('nameInput', ...(ngDevMode ? [{ debugName: "nameInput" }] : [])); suggestionButtons = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChildren)('suggestionButton', ...(ngDevMode ? [{ debugName: "suggestionButtons" }] : [])); ref = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__.DynamicDialogRef); config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(primeng_dynamicdialog__WEBPACK_IMPORTED_MODULE_6__.DynamicDialogConfig); maxLength = this.config.data?.maxLength ?? 60; form = new _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormGroup({ name: new _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormControl('', { nonNullable: true, validators: [_angular_forms__WEBPACK_IMPORTED_MODULE_3__.Validators.required, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.Validators.pattern(String.raw`.*\S.*`), _angular_forms__WEBPACK_IMPORTED_MODULE_3__.Validators.maxLength(this.maxLength)] }) }); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.afterEveryRender)(() => { const clamped = new Set(this.suggestionButtons().filter(({ nativeElement }) => nativeElement.scrollWidth > nativeElement.clientWidth).map(({ nativeElement }) => nativeElement.textContent?.trim() ?? '')); if (!(0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_11__.isEqualSet)(clamped, this.clampedSuggestions())) this.clampedSuggestions.set(clamped); }); } refreshNameSuggestions = () => { const allNames = this.config.data?.structureNameSuggestions?.(); if (!allNames || allNames.length === 0) { this.filteredNameSuggestions.set([]); } else { const query = (this.form.controls.name.value ?? '').trim().toLowerCase(); this.filteredNameSuggestions.set(query ? allNames.filter(name => name.toLowerCase().includes(query)) : allNames); } this.syncSuggestionsPopover(); }; selectNameSuggestion(name) { this.form.controls.name.setValue(name.slice(0, this.maxLength)); const popover = this.suggestionsPopover(); popover?.hide(); } /** Clears the field's current text (without saving) so a new name can be typed or picked * from the suggestions list, no backspacing required. */ clearName = () => { this.form.controls.name.setValue(''); this.refreshNameSuggestions(); this.nameInput()?.nativeElement.focus(); }; syncSuggestionsPopover() { const input = this.nameInput()?.nativeElement; const popover = this.suggestionsPopover(); if (!popover || !input) return; if (this.filteredNameSuggestions().length > 0) { popover.show(undefined, input); } else { popover.hide(); } } ngOnInit() { this.form.patchValue({ name: this.config.data?.name }); } save() { if (!this.form.valid) return; this.ref.close(this.form.controls.name.value.trim()); } close() { this.ref.close(); } static ɵfac = function RenameDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RenameDialogComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineComponent"]({ type: RenameDialogComponent, selectors: [["lib-rename-dialog"]], viewQuery: function RenameDialogComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵviewQuerySignal"](ctx.suggestionsPopover, _c0, 5)(ctx.nameInput, _c1, 5)(ctx.suggestionButtons, _c2, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵqueryAdvance"](3); } }, decls: 16, vars: 12, consts: [["nameInput", ""], ["suggestionsPopover", ""], ["suggestionButton", ""], ["icon", ""], [1, "flex", "flex-col", "gap-6", "pt-2", 3, "ngSubmit", "formGroup"], [1, "flex", "items-center", "gap-1"], ["variant", "on", 1, "min-w-0", "flex-1"], ["pInputText", "", "id", "rename-input", "formControlName", "name", "fluid", "", "autofocus", "", 3, "blur", "input"], ["data-propagate-click", "", 3, "appendTo", "dismissable"], ["data-propagate-click", "", "data-test-id", "rename-dialog-ul-name-suggestions", 1, "max-h-48", "w-56", "overflow-auto", "text-sm"], ["for", "rename-input"], ["type", "button", "data-test-id", "rename-dialog-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "pTooltip", "ariaLabel", "pt"], [1, "flex", "justify-end", "gap-2"], ["type", "button", "outlined", "", "severity", "secondary", "size", "small", 3, "onClick", "label"], ["type", "submit", "tabindex", "0", "severity", "contrast", "size", "small", 3, "label", "disabled"], ["type", "button", "data-propagate-click", "", "data-test-id", "rename-dialog-button-name-suggestion", 1, "hover:bg-surface-100", "dark:hover:bg-surface-700", "block", "w-full", "overflow-hidden", "rounded", "px-2", "py-1", "text-left", "text-ellipsis", "whitespace-nowrap", "text-inherit", 3, "mousedown", "click", "pTooltip", "tooltipPosition"], ["type", "button", "data-test-id", "rename-dialog-p-button-clear-name", "severity", "secondary", "text", "", "rounded", "", "size", "small", 3, "mousedown", "click", "pTooltip", "ariaLabel", "pt"], ["icon", "times", 1, "size-3"]], template: function RenameDialogComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](0, "form", 4); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("ngSubmit", function RenameDialogComponent_Template_form_ngSubmit_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.save()); }); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](1, "div", 5)(2, "p-floatlabel", 6)(3, "input", 7, 0); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("blur", function RenameDialogComponent_Template_input_blur_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); const suggestionsPopover_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵreference"](6); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]((ctx.config.data == null ? null : ctx.config.data.structureNameSuggestions) && (suggestionsPopover_r2 == null ? null : suggestionsPopover_r2.hide())); })("input", function RenameDialogComponent_Template_input_input_3_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]((ctx.config.data == null ? null : ctx.config.data.structureNameSuggestions) && ctx.refreshNameSuggestions()); }); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](5, "p-popover", 8, 1)(7, "ul", 9); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrepeaterCreate"](8, RenameDialogComponent_For_9_Template, 4, 3, "li", null, _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](10, "label", 10); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵconditionalCreate"](12, RenameDialogComponent_Conditional_12_Template, 5, 8, "p-button", 11); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementStart"](13, "div", 12)(14, "p-button", 13); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵlistener"]("onClick", function RenameDialogComponent_Template_p_button_onClick_14_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.close()); }); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelement"](15, "p-button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("formGroup", ctx.form); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵattribute"]("data-test-id", "rename-dialog-input-" + ((ctx.config.data == null ? null : ctx.config.data.label) || "name"))("maxlength", ctx.maxLength); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("appendTo", "body")("dismissable", false); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrepeater"](ctx.filteredNameSuggestions()); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵtextInterpolate"]((ctx.config.data == null ? null : ctx.config.data.label) || "Name"); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵconditional"](ctx.form.controls.name.value ? 12 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("label", (ctx.config.data == null ? null : ctx.config.data.cancelLabel) || "Cancel"); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵattribute"]("data-test-id", "rename-dialog-p-button-cancel-" + ((ctx.config.data == null ? null : ctx.config.data.cancelLabel) || "cancel")); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵproperty"]("label", (ctx.config.data == null ? null : ctx.config.data.saveLabel) || "Save")("disabled", ctx.form.invalid); _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵattribute"]("data-test-id", "rename-dialog-p-button-save-" + ((ctx.config.data == null ? null : ctx.config.data.saveLabel) || "save")); } }, dependencies: [primeng_inputtext__WEBPACK_IMPORTED_MODULE_8__.InputTextModule, primeng_inputtext__WEBPACK_IMPORTED_MODULE_8__.InputText, primeng_button__WEBPACK_IMPORTED_MODULE_5__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_5__.Button, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.ReactiveFormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_3__["ɵNgNoValidate"], _angular_forms__WEBPACK_IMPORTED_MODULE_3__.DefaultValueAccessor, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.NgControlStatusGroup, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormGroupDirective, _angular_forms__WEBPACK_IMPORTED_MODULE_3__.FormControlName, primeng_floatlabel__WEBPACK_IMPORTED_MODULE_7__.FloatLabel, primeng_popover__WEBPACK_IMPORTED_MODULE_9__.PopoverModule, primeng_popover__WEBPACK_IMPORTED_MODULE_9__.Popover, primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_10__.Tooltip, _icon_icon_component__WEBPACK_IMPORTED_MODULE_12__.IconComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2 }); } /***/ }, /***/ 5087 /*!*********************************************************!*\ !*** ./libs/ui/src/lib/row-menu/row-menu.controller.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ RowMenuController: () => (/* binding */ RowMenuController) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); class RowMenuController { build; items = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)([], ...(ngDevMode ? [{ debugName: "items" }] : [])); popup; contextMenu; /** * @param build Produces the menu for a row. `anchor` is the element the menu was opened * from, for items that need to position something of their own (a popover, say). */ constructor(build) { this.build = build; } openFromButton(menu, event, row) { event.stopPropagation(); this.popup = menu; if (this.contextMenu?.visible()) this.contextMenu.hide(); this.setItems(row, event.currentTarget); menu.toggle(event); } openAtPointer(menu, event, row) { event.preventDefault(); event.stopPropagation(); this.contextMenu = menu; this.popup?.hide(); this.setItems(row, event.target); menu.show(event); } setItems(row, anchor) { this.items.set(this.build(row, anchor instanceof HTMLElement ? anchor : undefined)); } } /***/ }, /***/ 32868 /*!**************************************************************************!*\ !*** ./libs/ui/src/lib/s-curve-graph-base/components/curve.component.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CurveComponent: () => (/* binding */ CurveComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 14975); /* eslint-disable @angular-eslint/component-selector */ const _c0 = ["lib-curve", ""]; function CurveComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdomElement"](0, "path", 2); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("d", ctx_r0.path())("stroke", ctx_r0.curve().color)("stroke-width", ctx_r0.strokeWidth() + ctx_r0.outlineWidthAddition)("stroke-opacity", ctx_r0.outlineOpacity); } } // A selected (or hovered) curve gets a soft outer glow in its own color behind the main // stroke, so it reads as clearly highlighted even when it overlaps other curves of a // similar hue - plain thickness alone got lost in a busy dark-theme plot. const OUTLINE_WIDTH_ADDITION = 6; const OUTLINE_OPACITY = 0.35; class CurveComponent { outlineWidthAddition = OUTLINE_WIDTH_ADDITION; outlineOpacity = OUTLINE_OPACITY; curve = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "curve" }] : [])); width = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(100, ...(ngDevMode ? [{ debugName: "width" }] : [])); scale = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(1, ...(ngDevMode ? [{ debugName: "scale" }] : [])); lineWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(2, ...(ngDevMode ? [{ debugName: "lineWidth" }] : [])); highlighted = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const curve = this.curve(); return curve.selected || curve.hovered; }, ...(ngDevMode ? [{ debugName: "highlighted" }] : [])); strokeWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const baseWidth = this.lineWidth(); return this.highlighted() ? baseWidth * 2 : baseWidth; }, ...(ngDevMode ? [{ debugName: "strokeWidth" }] : [])); path = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const original = this.curve().path; const width = this.width(); const scale = this.scale(); const scaledPoints = original.map(([x, y]) => [width / 2 + x * scale, width / 2 + y * scale * -1]); const [firstPoint] = scaledPoints; if (!firstPoint) return ''; return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_2__.buildSvgPath)(scaledPoints); }, ...(ngDevMode ? [{ debugName: "path" }] : [])); static ɵfac = function CurveComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CurveComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineComponent"]({ type: CurveComponent, selectors: [["", "lib-curve", ""]], inputs: { curve: [1, "curve"], width: [1, "width"], scale: [1, "scale"], lineWidth: [1, "lineWidth"] }, attrs: _c0, decls: 4, vars: 7, consts: [[1, "pointer-events-auto"], ["fill", "none", "stroke-linecap", "round", "stroke-linejoin", "round", 1, "pointer-events-stroke", "opacity-0"], ["fill", "none", "stroke-linecap", "round", "stroke-linejoin", "round", 1, "pointer-events-none"]], template: function CurveComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdomElementStart"](0, "g", 0); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdomElement"](1, "path", 1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditionalCreate"](2, CurveComponent_Conditional_2_Template, 1, 4, ":svg:path", 2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdomElement"](3, "path", 2); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("d", ctx.path())("stroke", "transparent")("stroke-width", ctx.strokeWidth() + 10); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵconditional"](ctx.highlighted() ? 2 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("d", ctx.path())("stroke", ctx.curve().color)("stroke-width", ctx.strokeWidth()); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 20601 /*!*************************************************************************!*\ !*** ./libs/ui/src/lib/s-curve-graph-base/components/grid.component.ts ***! \*************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GridComponent: () => (/* binding */ GridComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); /* eslint-disable @angular-eslint/component-selector */ const _c0 = ["lib-grid", ""]; function GridComponent_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "line", 1)(1, "line", 1); } if (rf & 2) { const line_r1 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", 0)("x2", ctx_r1.width())("y1", line_r1)("y2", line_r1)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", line_r1)("x2", line_r1)("y1", 0)("y2", ctx_r1.height())("stroke-width", 1); } } class GridComponent { width = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "width" }] : [])); height = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "height" }] : [])); divisions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(18, ...(ngDevMode ? [{ debugName: "divisions" }] : [])); lines = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const numberLines = this.divisions(); const width = this.width(); const gapSize = width / numberLines; const lines = []; for (let index = 0; index < numberLines; index++) { lines.push(index * gapSize); } return lines; }, ...(ngDevMode ? [{ debugName: "lines" }] : [])); static ɵfac = function GridComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || GridComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: GridComponent, selectors: [["", "lib-grid", ""]], inputs: { width: [1, "width"], height: [1, "height"], divisions: [1, "divisions"] }, attrs: _c0, decls: 3, vars: 0, consts: [[1, "pointer-events-none"], [1, "stroke-(--p-app-graph-grid)"]], template: function GridComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "g", 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeaterCreate"](1, GridComponent_For_2_Template, 2, 10, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeater"](ctx.lines()); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 35769 /*!**************************************************************************!*\ !*** ./libs/ui/src/lib/s-curve-graph-base/components/point.component.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PointComponent: () => (/* binding */ PointComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); /* eslint-disable @angular-eslint/component-selector */ const _c0 = ["lib-point", ""]; function PointComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "circle", 0); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("r", ctx_r0.scaledRadius() * ctx_r0.haloRadiusFactor)("cx", ctx_r0.x())("cy", ctx_r0.y())("fill", ctx_r0.color())("fill-opacity", ctx_r0.haloOpacity); } } // A point that's hovered (or being dragged) is rendered "active": filled in its own color // with a black outline and a soft halo, so it reads clearly over overlapping curves. An // inactive point stays a hollow black marker with just a colored outline, so a busy plot // full of points doesn't turn into a wall of solid color. const HALO_RADIUS_FACTOR = 2.5; const HALO_OPACITY = 0.25; const MARKER_STROKE_WIDTH = 1.5; class PointComponent { haloRadiusFactor = HALO_RADIUS_FACTOR; haloOpacity = HALO_OPACITY; markerStrokeWidth = MARKER_STROKE_WIDTH; radius = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(4, ...(ngDevMode ? [{ debugName: "radius" }] : [])); point = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "point" }] : [])); width = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(100, ...(ngDevMode ? [{ debugName: "width" }] : [])); scale = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(1, ...(ngDevMode ? [{ debugName: "scale" }] : [])); dragged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "dragged" }] : [])); /** Hovered or being dragged - the one point a user is currently focused on. */ active = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const dragged = this.dragged(); const hovered = this.point().hovered; return dragged || hovered; }, ...(ngDevMode ? [{ debugName: "active" }] : [])); scaledRadius = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const base = this.radius(); const active = this.active(); return active ? base + 1 : base; }, ...(ngDevMode ? [{ debugName: "scaledRadius" }] : [])); x = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.width() / 2 + this.point().position[0] * this.scale(), ...(ngDevMode ? [{ debugName: "x" }] : [])); y = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.width() / 2 + this.point().position[1] * this.scale() * -1, ...(ngDevMode ? [{ debugName: "y" }] : [])); color = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.point().color, ...(ngDevMode ? [{ debugName: "color" }] : [])); static ɵfac = function PointComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PointComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: PointComponent, selectors: [["", "lib-point", ""]], inputs: { radius: [1, "radius"], point: [1, "point"], width: [1, "width"], scale: [1, "scale"], dragged: [1, "dragged"] }, attrs: _c0, decls: 3, vars: 7, consts: [[1, "pointer-events-none"]], template: function PointComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "g"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](1, PointComponent_Conditional_1_Template, 1, 5, ":svg:circle", 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](2, "circle"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx.active() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("r", ctx.scaledRadius())("cx", ctx.x())("cy", ctx.y())("fill", ctx.active() ? ctx.color() : "#000000")("stroke", ctx.active() ? "#000000" : ctx.color())("stroke-width", ctx.markerStrokeWidth); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 75833 /*!**************************************************************************!*\ !*** ./libs/ui/src/lib/s-curve-graph-base/components/scale.component.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ScaleComponent: () => (/* binding */ ScaleComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); /* eslint-disable @angular-eslint/component-selector */ const _c0 = ["lib-scale", ""]; function ScaleComponent_For_4_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "text", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { const line_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const center_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](1); const tickTextGap_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", ctx_r1.width() / 2 - 5 - tickTextGap_r4)("y", center_r3 - line_r1.position)("stroke", "none")("font-size", ctx_r1.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", line_r1.value, " "); } } function ScaleComponent_For_4_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "text", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { const line_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const center_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](1); const tickTextGap_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", ctx_r1.width() / 2 - 5 - tickTextGap_r4)("y", center_r3 + line_r1.position)("stroke", "none")("font-size", ctx_r1.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", line_r1.value, " "); } } function ScaleComponent_For_4_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "text", 6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { const line_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const center_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](1); const tickTextGap_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", center_r3 - line_r1.position)("y", ctx_r1.height() / 2 + 5 + tickTextGap_r4)("font-size", ctx_r1.fontSize())("stroke", "none"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", line_r1.value, " "); } } function ScaleComponent_For_4_Conditional_7_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "text", 6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); } if (rf & 2) { const line_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const center_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](1); const tickTextGap_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", center_r3 + line_r1.position)("y", ctx_r1.height() / 2 + 5 + tickTextGap_r4)("font-size", ctx_r1.fontSize())("stroke", "none"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", line_r1.value, " "); } } function ScaleComponent_For_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](1, ScaleComponent_For_4_Conditional_1_Template, 2, 5, ":svg:text", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](2, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](3, ScaleComponent_For_4_Conditional_3_Template, 2, 5, ":svg:text", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](4, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](5, ScaleComponent_For_4_Conditional_5_Template, 2, 5, ":svg:text", 6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](6, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](7, ScaleComponent_For_4_Conditional_7_Template, 2, 5, ":svg:text", 6); } if (rf & 2) { const line_r1 = ctx.$implicit; const ɵ$index_5_r5 = ctx.$index; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const center_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreadContextLet"](1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", ctx_r1.width() / 2 - 5)("y1", center_r3 - line_r1.position)("x2", ctx_r1.width() / 2)("y2", center_r3 - line_r1.position)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ɵ$index_5_r5 % 2 !== 0 ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", ctx_r1.width() / 2 - 5)("y1", center_r3 + line_r1.position)("x2", ctx_r1.width() / 2)("y2", center_r3 + line_r1.position)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ɵ$index_5_r5 % 2 !== 0 ? 3 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", center_r3 - line_r1.position)("y1", ctx_r1.height() / 2)("x2", center_r3 - line_r1.position)("y2", ctx_r1.height() / 2 + 5)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ɵ$index_5_r5 % 2 !== 0 ? 5 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", center_r3 + line_r1.position)("y1", ctx_r1.height() / 2)("x2", center_r3 + line_r1.position)("y2", ctx_r1.height() / 2 + 5)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ɵ$index_5_r5 % 2 !== 0 ? 7 : -1); } } class ScaleComponent { scaleX = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(90, ...(ngDevMode ? [{ debugName: "scaleX" }] : [])); scaleY = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(90, ...(ngDevMode ? [{ debugName: "scaleY" }] : [])); quadrantDivisions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(9, ...(ngDevMode ? [{ debugName: "quadrantDivisions" }] : [])); fontSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(9, ...(ngDevMode ? [{ debugName: "fontSize" }] : [])); width = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "width" }] : [])); height = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "height" }] : [])); gapSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const numberLines = this.quadrantDivisions(); const width = this.width() / 2; return width / numberLines; }, ...(ngDevMode ? [{ debugName: "gapSize" }] : [])); lines = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const numberLines = this.quadrantDivisions(); const gapSize = this.gapSize(); const lines = []; for (let index = 1; index < numberLines; index++) { lines.push({ position: index * gapSize, value: index * 10 }); } return lines; }, ...(ngDevMode ? [{ debugName: "lines" }] : [])); static ɵfac = function ScaleComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ScaleComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: ScaleComponent, selectors: [["", "lib-scale", ""]], inputs: { scaleX: [1, "scaleX"], scaleY: [1, "scaleY"], quadrantDivisions: [1, "quadrantDivisions"], fontSize: [1, "fontSize"], width: [1, "width"], height: [1, "height"] }, attrs: _c0, decls: 15, vars: 29, consts: [["fill", "#FFFFFF", "stroke", "none", 1, "pointer-events-none", "select-none"], ["pointer-events", "none", 1, "stroke-(--p-app-graph-axis)"], ["dominant-baseline", "hanging", 1, "fill-(--p-app-graph-label)"], ["dominant-baseline", "text-after-edge", 1, "fill-(--p-app-graph-label)"], ["text-anchor", "start", "dominant-baseline", "central", 1, "fill-(--p-app-graph-label)"], ["text-anchor", "end", "dominant-baseline", "central", 1, "fill-(--p-app-graph-label)"], ["text-anchor", "middle", "dominant-baseline", "hanging", 1, "fill-(--p-app-graph-label)"]], template: function ScaleComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](0, "g", 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdeclareLet"](1)(2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeaterCreate"](3, ScaleComponent_For_4_Template, 8, 24, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](5, "line", 1)(6, "line", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](7, "text", 2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](8, " CRAN "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](9, "text", 3); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](10, " CAUD "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](11, "text", 4); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](12, " RAO "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementStart"](13, "text", 5); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](14, " LAO "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("font-size", ctx.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstoreLet"](ctx.width() / 2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); const tickTextGap_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵstoreLet"](4); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeater"](ctx.lines()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", 0)("y1", ctx.height() / 2)("x2", ctx.width())("y2", ctx.height() / 2)("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x1", ctx.width() / 2)("y1", 0)("x2", ctx.width() / 2)("y2", ctx.height())("stroke-width", 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", ctx.width() / 2 + tickTextGap_r6)("y", tickTextGap_r6)("font-size", ctx.fontSize())("stroke", "none"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", ctx.width() / 2 + tickTextGap_r6)("y", ctx.height() - tickTextGap_r6)("font-size", ctx.fontSize())("stroke", "none"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", tickTextGap_r6)("y", ctx.width() / 2 - ctx.gapSize())("font-size", ctx.fontSize())("stroke", "none"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("x", ctx.width() - tickTextGap_r6)("y", ctx.width() / 2 - ctx.gapSize())("font-size", ctx.fontSize())("stroke", "none"); } }, encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 27608 /*!****************************************************************************!*\ !*** ./libs/ui/src/lib/s-curve-graph-base/s-curve-graph-base.component.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SCurveGraphBaseComponent: () => (/* binding */ SCurveGraphBaseComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _components_curve_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/curve.component */ 32868); /* harmony import */ var _components_grid_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/grid.component */ 20601); /* harmony import */ var _components_point_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/point.component */ 35769); /* harmony import */ var _components_scale_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/scale.component */ 75833); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["svgRoot"]; const _forTrack0 = ($index, $item) => $item.id; function SCurveGraphBaseComponent_For_5_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "g", 8); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function SCurveGraphBaseComponent_For_5_Template_g_click_0_listener($event) { const curve_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onCurveClick($event, curve_r3.id)); })("contextmenu", function SCurveGraphBaseComponent_For_5_Template_g_contextmenu_0_listener($event) { const curve_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onCurveContextMenu($event, curve_r3.id)); })("mouseover", function SCurveGraphBaseComponent_For_5_Template_g_mouseover_0_listener($event) { const curve_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onCurveHoverStart($event, curve_r3.id)); })("mouseout", function SCurveGraphBaseComponent_For_5_Template_g_mouseout_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r2); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onCurveHoverEnd($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const curve_r3 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("curve", curve_r3)("width", ctx_r3.width())("scale", ctx_r3.scale())("lineWidth", ctx_r3.lineWidth()); } } function SCurveGraphBaseComponent_For_7_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "g", 9); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("mousedown", function SCurveGraphBaseComponent_For_7_Template_g_mousedown_0_listener($event) { const point_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.pointMouseDown($event, point_r6.id)); })("click", function SCurveGraphBaseComponent_For_7_Template_g_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event.stopPropagation()); })("mouseover", function SCurveGraphBaseComponent_For_7_Template_g_mouseover_0_listener($event) { const point_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onPointHoverStart($event, point_r6.id)); })("mouseout", function SCurveGraphBaseComponent_For_7_Template_g_mouseout_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r3.onPointHoverEnd($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const point_r6 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("dragged", ctx_r3.isDragged(point_r6.id))("point", point_r6)("width", ctx_r3.width())("scale", ctx_r3.scale()); } } function SCurveGraphBaseComponent_For_9_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "text", 6); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const label_r7 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("x", label_r7.x)("y", label_r7.y)("fill", label_r7.color)("font-size", ctx_r3.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate1"](" ", label_r7.text, " "); } } function SCurveGraphBaseComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "g", 7); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](1, "line", 10)(2, "line", 10)(3, "rect", 11); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](4, "text", 12); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()(); } if (rf & 2) { const readout_r8 = ctx; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("x1", readout_r8.crosshairX)("y1", 0)("x2", readout_r8.crosshairX)("y2", ctx_r3.width()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("x1", 0)("y1", readout_r8.crosshairY)("x2", ctx_r3.width())("y2", readout_r8.crosshairY); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("x", readout_r8.boxX)("y", readout_r8.boxY)("width", readout_r8.boxWidth)("height", readout_r8.boxHeight); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("x", readout_r8.textX)("y", readout_r8.textY)("font-size", ctx_r3.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate1"](" ", readout_r8.text, " "); } } // Gap between a point's own edge and where its label starts. const LABEL_POINT_GAP = 6; // Text width can't be measured synchronously off-screen, so it's approximated from // character count - close enough to keep the declutter pass from under/over-spacing labels. const AVG_CHAR_WIDTH_FACTOR = 0.6; const LABEL_LINE_HEIGHT_FACTOR = 1.3; const DEFAULT_POINT_RADIUS = 4; // Bottom-edge angle readout shown while a point is active. const READOUT_BOTTOM_MARGIN = 4; const READOUT_PADDING_X = 6; const READOUT_VERTICAL_PADDING = 6; function estimateLabelWidth(text, fontSize) { return text.length * fontSize * AVG_CHAR_WIDTH_FACTOR; } function estimateLabelHeight(fontSize) { return fontSize * LABEL_LINE_HEIGHT_FACTOR; } class SCurveGraphBaseComponent { svgRoot = _angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild.required('svgRoot'); svgResize; width = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "width" }] : [])); height = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(0, ...(ngDevMode ? [{ debugName: "height" }] : [])); scale = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.width() / 180, ...(ngDevMode ? [{ debugName: "scale" }] : [])); draggedId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "draggedId" }] : [])); points = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)([], ...(ngDevMode ? [{ debugName: "points" }] : [])); curves = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)([], ...(ngDevMode ? [{ debugName: "curves" }] : [])); fontSize = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(9, ...(ngDevMode ? [{ debugName: "fontSize" }] : [])); lineWidth = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(2, ...(ngDevMode ? [{ debugName: "lineWidth" }] : [])); backgroundClicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); backgroundContextMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); pointHovered = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); pointMoved = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); pointSnappedToCurve = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); curveContextMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); curveSelected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); curveHovered = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); /** Labels for points that have one, laid out so none overlap. Only points with a * `label` set (e.g. saved chamber views) contribute - most point types render * unlabeled, exactly as before. */ labels = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const width = this.width(); const scale = this.scale(); const fontSize = this.fontSize(); const labeled = this.points().filter(point => point.label !== undefined); if (labeled.length === 0) return []; const boxes = labeled.map(point => { const screenX = width / 2 + point.position[0] * scale; const screenY = width / 2 + point.position[1] * scale * -1; const labelHeight = estimateLabelHeight(fontSize); return { anchorX: screenX + DEFAULT_POINT_RADIUS + LABEL_POINT_GAP, anchorY: screenY - labelHeight / 2, height: labelHeight, id: point.id, width: estimateLabelWidth(point.label, fontSize) }; }); const placementById = new Map((0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.declutterLabels)(boxes).map(p => [p.id, p])); return labeled.map(point => { const placement = placementById.get(point.id); return { color: point.color, id: point.id, text: point.label, x: placement?.x ?? 0, // SVG y is the baseline, not the box top - shift down by the font size // so the glyphs sit inside their decluttered box instead of above it. y: (placement?.y ?? 0) + fontSize }; }); }, ...(ngDevMode ? [{ debugName: "labels" }] : [])); /** The point a user is currently focused on - hovered, or mid-drag. Drives the crosshair * and angle readout below; most of the time there isn't one and both stay hidden. */ activePoint = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const dragged = this.draggedId(); return this.points().find(point => point.hovered || point.id === dragged); }, ...(ngDevMode ? [{ debugName: "activePoint" }] : [])); /** Crosshair position and bottom-edge angle readout for the active point. The box is * sized to its own text (same estimate used for point labels) so it stays legible * wherever it lands on top of the grid, curves, or the CAUD axis label. */ activePointReadout = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const point = this.activePoint(); if (!point) return; const width = this.width(); const scale = this.scale(); const fontSize = this.fontSize(); const [rl, cc] = point.position; const text = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.formatAngulationtxt)({ ax: 0, cc, rl }, false); const boxHeight = estimateLabelHeight(fontSize) + READOUT_VERTICAL_PADDING; const boxWidth = estimateLabelWidth(text, fontSize) + READOUT_PADDING_X * 2; const boxY = width - READOUT_BOTTOM_MARGIN - boxHeight; return { boxHeight, boxWidth, boxX: width / 2 - boxWidth / 2, boxY, crosshairX: width / 2 + rl * scale, crosshairY: width / 2 + cc * scale * -1, text, textX: width / 2, textY: boxY + boxHeight / 2 }; }, ...(ngDevMode ? [{ debugName: "activePointReadout" }] : [])); curveToSnap = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => { const selected = this.curves().filter(({ selected }) => selected); // Only snap if there is a single selection if (selected.length !== 1) { return; } return selected[0]; }, ...(ngDevMode ? [{ debugName: "curveToSnap" }] : [])); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DestroyRef).onDestroy(() => { this.svgResize?.disconnect(); this.svgResize = undefined; }); } ngAfterViewInit() { const svgResize = new ResizeObserver(entries => { for (const { contentRect } of entries) { this.width.set(contentRect.right - contentRect.left); this.height.set(contentRect.bottom - contentRect.top); } }); svgResize.observe(this.svgRoot().nativeElement); this.svgResize = svgResize; } pointMouseDown(event, pointId) { const point = this.points().find(({ id }) => id === pointId); if (point?.draggable === false) return; this.draggedId.set(pointId); if (point?.snappable === false) return; const curveToSnap = this.curveToSnap(); if (curveToSnap) { this.pointSnappedToCurve.emit({ curveId: curveToSnap.id, pointId }); } } onMouseMove(event) { const dragged = this.draggedId(); if (dragged === undefined) { return; } let newPosition = [event.offsetX / this.scale() - 90, -event.offsetY / this.scale() + 90]; let curveId; const draggedPoint = this.points().find(({ id }) => id === dragged); const curveToSnap = draggedPoint?.snappable === false ? undefined : this.curveToSnap(); if (curveToSnap) { const [rl, cc] = newPosition; const path3D = curveToSnap.path.map(([x, y]) => (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.position)(x, y, 0)); const distance = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculateDistanceOnPath)(path3D, [rl, cc, 0]); const length = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.calculatePathDistance)(path3D, false); const snapped = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.getPointAtDistance)(curveToSnap.path, distance / length); if (snapped) { curveId = curveToSnap.id; newPosition = snapped; } } this.pointMoved.emit({ curveId, newPosition, pointId: dragged }); } onMouseUp(event) { this.draggedId.set(undefined); } onBackgroundClick(event) { this.backgroundClicked.emit(); } onBackgroundContextMenu(event) { event.preventDefault(); event.stopPropagation(); this.backgroundContextMenu.emit({ event }); } onCurveClick(event, curveId) { event.preventDefault(); event.stopPropagation(); this.curveSelected.emit({ additive: event.ctrlKey || event.shiftKey, curveId }); } onCurveContextMenu(event, curveId) { event.preventDefault(); event.stopPropagation(); this.curveContextMenu.emit({ curveId, event }); } onCurveHoverStart(event, curveId) { this.curveHovered.emit({ curveId }); } onCurveHoverEnd(event) { this.curveHovered.emit({ curveId: undefined }); } onPointHoverStart(event, pointId) { this.pointHovered.emit({ pointId }); } onPointHoverEnd(event) { this.pointHovered.emit({ pointId: undefined }); } isDragged(id) { return id === this.draggedId(); } static ɵfac = function SCurveGraphBaseComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SCurveGraphBaseComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵdefineComponent"]({ type: SCurveGraphBaseComponent, selectors: [["lib-s-curve-graph-base"]], viewQuery: function SCurveGraphBaseComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵviewQuerySignal"](ctx.svgRoot, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵqueryAdvance"](); } }, inputs: { points: [1, "points"], curves: [1, "curves"], fontSize: [1, "fontSize"], lineWidth: [1, "lineWidth"] }, outputs: { backgroundClicked: "backgroundClicked", backgroundContextMenu: "backgroundContextMenu", pointHovered: "pointHovered", pointMoved: "pointMoved", pointSnappedToCurve: "pointSnappedToCurve", curveContextMenu: "curveContextMenu", curveSelected: "curveSelected", curveHovered: "curveHovered" }, decls: 11, vars: 6, consts: [["svgRoot", ""], [1, "aspect-square", "overflow-hidden", "bg-(--p-app-graph-background)", 3, "click", "contextmenu", "mousemove", "mouseup"], ["lib-grid", "", 3, "width", "height"], ["lib-scale", "", 3, "width", "height", "fontSize"], ["lib-curve", "", 3, "curve", "width", "scale", "lineWidth"], ["lib-point", "", 3, "dragged", "point", "width", "scale"], [1, "s-curve-point-label", "pointer-events-none", "select-none"], [1, "pointer-events-none"], ["lib-curve", "", 3, "click", "contextmenu", "mouseover", "mouseout", "curve", "width", "scale", "lineWidth"], ["lib-point", "", 3, "mousedown", "click", "mouseover", "mouseout", "dragged", "point", "width", "scale"], ["stroke", "#FFFFFF", "stroke-opacity", "0.6", "stroke-width", "1", "stroke-dasharray", "3 3"], ["rx", "3", "fill", "#000000", "fill-opacity", "0.75", "stroke", "#FFFFFF", "stroke-opacity", "0.4", "stroke-width", "1"], ["fill", "#FFFFFF", "text-anchor", "middle", "dominant-baseline", "central", 1, "s-curve-active-point-readout", "pointer-events-none", "select-none"]], template: function SCurveGraphBaseComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵnamespaceSVG"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "svg", 1, 0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function SCurveGraphBaseComponent_Template_svg_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onBackgroundClick($event)); })("contextmenu", function SCurveGraphBaseComponent_Template_svg_contextmenu_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onBackgroundContextMenu($event)); })("mousemove", function SCurveGraphBaseComponent_Template_svg_mousemove_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onMouseMove($event)); })("mouseup", function SCurveGraphBaseComponent_Template_svg_mouseup_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx.onMouseUp($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](2, "g", 2)(3, "g", 3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](4, SCurveGraphBaseComponent_For_5_Template, 1, 4, ":svg:g", 4, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](6, SCurveGraphBaseComponent_For_7_Template, 1, 4, ":svg:g", 5, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](8, SCurveGraphBaseComponent_For_9_Template, 2, 5, ":svg:text", 6, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](10, SCurveGraphBaseComponent_Conditional_10_Template, 6, 16, ":svg:g", 7); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_9_0; _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("width", ctx.width())("height", ctx.height()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("width", ctx.width())("height", ctx.height())("fontSize", ctx.fontSize()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx.curves()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx.points()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx.labels()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_9_0 = ctx.activePointReadout()) ? 10 : -1, tmp_9_0); } }, dependencies: [_components_curve_component__WEBPACK_IMPORTED_MODULE_4__.CurveComponent, _components_grid_component__WEBPACK_IMPORTED_MODULE_5__.GridComponent, _components_point_component__WEBPACK_IMPORTED_MODULE_6__.PointComponent, _components_scale_component__WEBPACK_IMPORTED_MODULE_7__.ScaleComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 55806 /*!************************************************************************!*\ !*** ./libs/ui/src/lib/scroll-to-active/scroll-to-active.directive.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ScrollToActiveDirective: () => (/* binding */ ScrollToActiveDirective) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); class ScrollToActiveDirective { element = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.ElementRef); document = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.DOCUMENT); isActive = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required({ ...(ngDevMode ? { debugName: "isActive" } : {}), alias: 'libScrollToActive' }); constructor() { (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { if (!this.isActive()) return; requestAnimationFrame(() => { const nativeElement = this.element.nativeElement; nativeElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); if (this.document.activeElement?.tagName !== 'INPUT' && this.document.activeElement?.tagName !== 'TEXTAREA') { nativeElement.focus({ preventScroll: true }); } }); }); } static ɵfac = function ScrollToActiveDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ScrollToActiveDirective)(); }; static ɵdir = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefineDirective"]({ type: ScrollToActiveDirective, selectors: [["", "libScrollToActive", ""]], inputs: { isActive: [1, "libScrollToActive", "isActive"] } }); } /***/ }, /***/ 27620 /*!********************************************************************!*\ !*** ./libs/ui/src/lib/section-button/section-button.component.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SectionButtonComponent: () => (/* binding */ SectionButtonComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/api */ 62751); function SectionButtonComponent_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](0, "lib-icon", 2); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("icon", ctx_r0.icon()); } } /** Icon-only toggle for a drawer section. */ class SectionButtonComponent { icon = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "icon" }] : [])); name = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "name" }] : [])); color = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "color" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "selected" }] : [])); lightBackground = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, { ...(ngDevMode ? { debugName: "lightBackground" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_0__.booleanAttribute }); label = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "label" }] : [])); tooltipPosition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('left', ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : [])); activate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); buttonDt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const color = this.color(); const selected = this.selected(); const idleBackground = this.lightBackground() ? 'var(--p-app-section-contrast)' : 'var(--p-app-chrome-app-header)'; const background = selected ? color : idleBackground; const foreground = selected ? 'var(--p-app-section-contrast)' : color; const borderColor = selected ? 'transparent' : color; const hoverBackground = selected ? color : `color-mix(in srgb, ${color} 16%, ${idleBackground})`; return { root: { primary: { activeBackground: hoverBackground, activeBorderColor: borderColor, activeColor: foreground, background, borderColor, color: foreground, focusRing: { color }, hoverBackground, hoverBorderColor: borderColor, hoverColor: foreground } } }; }, ...(ngDevMode ? [{ debugName: "buttonDt" }] : [])); buttonPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => ({ root: { 'aria-pressed': this.selected() } }), ...(ngDevMode ? [{ debugName: "buttonPt" }] : [])); static ɵfac = function SectionButtonComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SectionButtonComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: SectionButtonComponent, selectors: [["lib-section-button"]], inputs: { icon: [1, "icon"], name: [1, "name"], color: [1, "color"], selected: [1, "selected"], lightBackground: [1, "lightBackground"], label: [1, "label"], tooltipPosition: [1, "tooltipPosition"] }, outputs: { activate: "activate" }, decls: 2, vars: 6, consts: [["styleClass", "size-9", 3, "click", "dt", "ariaLabel", "pt", "pTooltip", "tooltipPosition"], ["pTemplate", "icon"], [1, "size-(--p-app-font-size-sm)", "text-(length:--p-app-font-size-sm)", 3, "icon"]], template: function SectionButtonComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "p-button", 0); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("click", function SectionButtonComponent_Template_p_button_click_0_listener() { return ctx.activate.emit(); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵtemplate"](1, SectionButtonComponent_ng_template_1_Template, 1, 1, "ng-template", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("dt", ctx.buttonDt())("ariaLabel", ctx.label())("pt", ctx.buttonPt())("pTooltip", ctx.label())("tooltipPosition", ctx.tooltipPosition()); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵattribute"]("data-test-id", "section-button-p-button-" + ctx.name()); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, primeng_api__WEBPACK_IMPORTED_MODULE_6__.PrimeTemplate, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__.IconComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 10458 /*!************************************************************************!*\ !*** ./libs/ui/src/lib/settings-popover/settings-popover.component.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SettingsPopoverComponent: () => (/* binding */ SettingsPopoverComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _angular_forms_signals__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/forms/signals */ 90531); /* harmony import */ var _angular_forms_signals__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/forms/signals */ 84066); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_divider__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/divider */ 1432); /* harmony import */ var primeng_popover__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! primeng/popover */ 91124); /* harmony import */ var primeng_select__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! primeng/select */ 6989); /* harmony import */ var primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! primeng/toggleswitch */ 79945); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../viewport-button/viewport-button.component */ 14486); /* harmony import */ var _viewport_setting_slider_viewport_setting_slider_component__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../viewport-setting-slider/viewport-setting-slider.component */ 346); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! primeng/api */ 62751); const _c0 = ["popover"]; const _c1 = a0 => ({ "group-selection": a0 }); const _forTrack0 = ($index, $item) => $item.name; function SettingsPopoverComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "lib-viewport-button", 10, 1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("click", function SettingsPopoverComponent_Conditional_0_Template_lib_viewport_button_click_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); const popover_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵreference"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](popover_r3.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("tooltip", ctx_r3.buttonTooltip())("ariaLabel", ctx_r3.buttonAriaLabel()); } } function SettingsPopoverComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "span", 11); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("mousedown", function SettingsPopoverComponent_Conditional_7_Template_span_mousedown_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r5); const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r3.startDrag($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](1, "lib-icon", 12); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("aria-label", ctx_r3.dragHandleAriaLabel()); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 18)(1, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()(); } if (rf & 2) { const group_r8 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate"](group_r8.label); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "div", 19); } if (rf & 2) { const item_r9 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("innerHTML", item_r9.label, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵsanitizeHtml"]); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "div", 20); } if (rf & 2) { const selectedOption_r10 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("innerHTML", selectedOption_r10.label, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵsanitizeHtml"]); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtemplate"](0, SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_0_Template, 3, 1, "ng-template", 15)(1, SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_1_Template, 1, 1, "ng-template", 16)(2, SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_ng_template_2_Template, 1, 1, "ng-template", 17); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 13)(1, "p-select", 14); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("onChange", function SettingsPopoverComponent_Conditional_10_For_2_Case_0_Template_p_select_onChange_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r6); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r3.onSelectChange(formField_r7)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](3, SettingsPopoverComponent_Conditional_10_For_2_Case_0_Conditional_3_Template, 3, 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrolCreate"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("options", formField_r7.options())("group", formField_r7.group)("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpureFunction1"](10, _c1, formField_r7.group))("placeholder", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](2, 8, formField_r7.label)); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("data-test-id", `settings-popover-p-select-${formField_r7.name}`); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrol"](ctx_r3.ctForm[formField_r7.name], "formField"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](formField_r7.selectOptionsTemplate === ctx_r3.selecteOptionsTemplate.CT_SELECT_OPTIONS ? 3 : -1); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_1_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "lib-icon", 22); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2).$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("icon", formField_r7.icon); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_1_Template(rf, ctx) { if (rf & 1) { const _r11 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 13)(1, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("onClick", function SettingsPopoverComponent_Conditional_10_For_2_Case_1_Template_p_button_onClick_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r11); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.onTrigger($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](2, SettingsPopoverComponent_Conditional_10_For_2_Case_1_Conditional_2_Template, 1, 1, "lib-icon", 22); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](3, "span", 23); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](5, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()()(); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("data-test-id", "settings-popover-p-button-" + formField_r7.name); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](formField_r7.icon ? 2 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](5, 3, formField_r7.label)); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_2_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "p-divider", 8); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_2_Template(rf, ctx) { if (rf & 1) { const _r12 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 13)(1, "p-button", 24); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("onClick", function SettingsPopoverComponent_Conditional_10_For_2_Case_2_Template_p_button_onClick_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r12); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.onClick(ctx_r3.ctForm)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](3, SettingsPopoverComponent_Conditional_10_For_2_Case_2_Conditional_3_Template, 1, 0, "p-divider", 8); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](2, 4, formField_r7.label))("disabled", formField_r7.disabled ?? false); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("data-test-id", `settings-popover-p-button-${formField_r7.name}`); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](formField_r7.hasDivider ? 3 : -1); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "p-divider", 8); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template(rf, ctx) { if (rf & 1) { const _r13 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 13)(1, "lib-viewport-setting-slider", 25); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](2, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("sliderValueChanged", function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template_lib_viewport_setting_slider_sliderValueChanged_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r13); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r3.onSliderValueChange(formField_r7, $event)); })("slideEnd", function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template_lib_viewport_setting_slider_slideEnd_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r13); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.onSlideEnd == null ? null : formField_r7.onSlideEnd($event)); })("resetClicked", function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template_lib_viewport_setting_slider_resetClicked_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r13); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.resetEvent(ctx_r3.ctForm)); })("dragStart", function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template_lib_viewport_setting_slider_dragStart_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r13); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.onDragStart == null ? null : formField_r7.onDragStart()); })("dragEnd", function SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template_lib_viewport_setting_slider_dragEnd_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r13); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](formField_r7.onDragEnd == null ? null : formField_r7.onDragEnd()); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrolCreate"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](3, SettingsPopoverComponent_Conditional_10_For_2_Case_3_Conditional_3_Template, 1, 0, "p-divider", 8); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("label", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](2, 12, formField_r7.label))("minValue", ctx_r3.resolveFieldBound(formField_r7.name + "-min", formField_r7.min))("maxValue", ctx_r3.resolveFieldBound(formField_r7.name + "-max", formField_r7.max))("step", formField_r7.step ?? 1)("isDisabled", formField_r7.disabled ?? false)("tooltip", formField_r7.tooltip)("showValue", formField_r7.showValue ?? false)("valueSuffix", formField_r7.valueSuffix ?? "")("valueFormatter", formField_r7.valueFormatter); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrol"](ctx_r3.ctForm[formField_r7.name], "formField"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](formField_r7.hasDivider ? 3 : -1); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_4_Conditional_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](0, "p-divider", 8); } } function SettingsPopoverComponent_Conditional_10_For_2_Case_4_Template(rf, ctx) { if (rf & 1) { const _r14 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "div", 26)(1, "label", 27); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipe"](3, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](4, "p-toggleswitch", 28); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("onChange", function SettingsPopoverComponent_Conditional_10_For_2_Case_4_Template_p_toggleswitch_onChange_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r14); const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r3.onToggleChange(formField_r7, $event.checked)); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrolCreate"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](5, SettingsPopoverComponent_Conditional_10_For_2_Case_4_Conditional_5_Template, 1, 0, "p-divider", 8); } if (rf & 2) { const formField_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"]().$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("for", formField_r7.name); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵpipeBind1"](3, 7, formField_r7.label), " "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵproperty"]("inputId", formField_r7.name); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("data-test-id", `settings-popover-p-toggleswitch-${formField_r7.name}`); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵcontrol"](ctx_r3.ctForm[formField_r7.name], "formField"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](formField_r7.hasDivider ? 5 : -1); } } function SettingsPopoverComponent_Conditional_10_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](0, SettingsPopoverComponent_Conditional_10_For_2_Case_0_Template, 4, 12, "div", 13)(1, SettingsPopoverComponent_Conditional_10_For_2_Case_1_Template, 6, 5, "div", 13)(2, SettingsPopoverComponent_Conditional_10_For_2_Case_2_Template, 4, 6)(3, SettingsPopoverComponent_Conditional_10_For_2_Case_3_Template, 4, 14)(4, SettingsPopoverComponent_Conditional_10_For_2_Case_4_Template, 6, 9); } if (rf & 2) { let tmp_12_0; const formField_r7 = ctx.$implicit; const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"]((tmp_12_0 = formField_r7.type) === ctx_r3.settingsPopoverField.SELECT ? 0 : tmp_12_0 === ctx_r3.settingsPopoverField.MENU_BUTTON ? 1 : tmp_12_0 === ctx_r3.settingsPopoverField.BUTTON ? 2 : tmp_12_0 === ctx_r3.settingsPopoverField.SLIDER ? 3 : tmp_12_0 === ctx_r3.settingsPopoverField.TOGGLE ? 4 : -1); } } function SettingsPopoverComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](0, "form"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeaterCreate"](1, SettingsPopoverComponent_Conditional_10_For_2_Template, 5, 1, null, null, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r3 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵrepeater"](ctx_r3.formFieldConfig()); } } class SettingsPopoverComponent { buttonTooltip = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('', ...(ngDevMode ? [{ debugName: "buttonTooltip" }] : [])); buttonAriaLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('', ...(ngDevMode ? [{ debugName: "buttonAriaLabel" }] : [])); title = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('', ...(ngDevMode ? [{ debugName: "title" }] : [])); isDarkMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, { ...(ngDevMode ? { debugName: "isDarkMode" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_1__.booleanAttribute }); formFieldConfig = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)([], ...(ngDevMode ? [{ debugName: "formFieldConfig" }] : [])); popoverTarget = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "popoverTarget" }] : [])); showButton = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, { ...(ngDevMode ? { debugName: "showButton" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_1__.booleanAttribute }); externalOpen = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, { ...(ngDevMode ? { debugName: "externalOpen" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_1__.booleanAttribute }); draggable = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, { ...(ngDevMode ? { debugName: "draggable" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_1__.booleanAttribute }); dragHandleAriaLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('Move', ...(ngDevMode ? [{ debugName: "dragHandleAriaLabel" }] : [])); dragBoundary = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "dragBoundary" }] : [])); visibilityChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); closed = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); settingsPopoverField = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.SettingsPopoverField; initialized = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)(false, ...(ngDevMode ? [{ debugName: "initialized" }] : [])); popoverRef; el = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.ElementRef); ngZone = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.NgZone); renderer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_3__.Renderer2); ctFormFields = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.signal)({}, ...(ngDevMode ? [{ debugName: "ctFormFields" }] : [])); ctForm = (0,_angular_forms_signals__WEBPACK_IMPORTED_MODULE_6__.form)(this.ctFormFields); selecteOptionsTemplate = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_13__.SelectOptionsTemplate; lastStoreFields = {}; constructor() { const formConfigEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const config = this.formFieldConfig(); if (config.length > 0) { const newFields = Object.fromEntries(config.map(item => [item.name, item.defaultValue])); // Only hide/re-show the panel on structural changes (e.g. preset switch where the // set of fields changes). Slider value updates must not hide the panel — that causes flicker. const panel = this.popoverRef?.container; const currentFieldNames = new Set(Object.keys((0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.untracked)(() => this.ctFormFields()))); const newFieldNames = new Set(Object.keys(newFields)); const isStructuralChange = currentFieldNames.size !== newFieldNames.size || [...newFieldNames].some(k => !currentFieldNames.has(k)); if (panel && this.externalOpen() && isStructuralChange) panel.style.visibility = 'hidden'; if (isStructuralChange) { this.ctFormFields.set(newFields); } else { this.reflectStoreChanges(newFields); } this.lastStoreFields = newFields; this.initialized.set(true); if (this.externalOpen() && isStructuralChange) { setTimeout(() => { this.centerOverAnchor(); if (panel) panel.style.visibility = ''; }); } } }, ...(ngDevMode ? [{ debugName: "formConfigEffect" }] : [])); const externalOpenEffect = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { const open = this.externalOpen(); const target = this.popoverTarget() ?? this.el.nativeElement; setTimeout(() => { if (open) { this.popoverRef?.show?.(new MouseEvent('click'), target); } else { this.popoverRef?.hide?.(); } }); }, ...(ngDevMode ? [{ debugName: "externalOpenEffect" }] : [])); (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.DestroyRef).onDestroy(() => { formConfigEffect.destroy(); externalOpenEffect.destroy(); this.stopDrag(); }); } /** Write back only fields whose store value changed, so one slider's edit can't reset another. */ reflectStoreChanges(newFields) { const changedKeys = Object.keys(newFields).filter(key => newFields[key] !== this.lastStoreFields[key]); if (changedKeys.length > 0) { const patch = Object.fromEntries(changedKeys.map(key => [key, newFields[key]])); this.ctFormFields.update(fields => ({ ...fields, ...patch })); } } boundSignals = new Map(); /** Mutable drag state for the move handle */ drag = { anchor: { height: 0, left: 0, top: 0, width: 0 }, bounds: undefined, offset: { x: 0, y: 0 }, origin: { x: 0, y: 0 }, removeMove: undefined, removeUp: undefined }; startDrag(event) { if (!this.draggable()) return; event.preventDefault(); this.drag.origin = { x: event.clientX - this.drag.offset.x, y: event.clientY - this.drag.offset.y }; const rect = this.popoverRef?.container?.getBoundingClientRect(); if (rect) { this.drag.anchor = { height: rect.height, left: rect.left - this.drag.offset.x, top: rect.top - this.drag.offset.y, width: rect.width }; } this.drag.bounds = (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.resolveBoundaryRect)(this.dragBoundary(), this.el.nativeElement); this.ngZone.runOutsideAngular(() => { this.drag.removeMove = this.renderer.listen('document', 'mousemove', move => this.onDrag(move)); this.drag.removeUp = this.renderer.listen('document', 'mouseup', () => this.stopDrag()); }); } onDrag(event) { const offset = { x: event.clientX - this.drag.origin.x, y: event.clientY - this.drag.origin.y }; this.drag.offset = this.drag.bounds ? (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_14__.clampOffsetWithinBounds)(offset, this.drag.anchor, this.drag.bounds) : offset; const panel = this.popoverRef?.container; if (panel) { panel.style.transform = `translate3d(${this.drag.offset.x}px, ${this.drag.offset.y}px, 0)`; } } stopDrag() { this.drag.removeMove?.(); this.drag.removeUp?.(); this.drag.removeMove = undefined; this.drag.removeUp = undefined; } resetPosition() { this.drag.offset = { x: 0, y: 0 }; const panel = this.popoverRef?.container; if (panel) panel.style.transform = ''; } centerOverAnchor() { if (this.showButton()) return; const panel = this.popoverRef?.container; if (!panel) return; const anchor = this.el.nativeElement.getBoundingClientRect(); const left = anchor.left + anchor.width / 2 - panel.offsetWidth / 2; panel.style.insetInlineStart = `${Math.max(0, left)}px`; } /** * PrimeNG dismisses the popover on an outside left-click, but not on right-click. * Mirror that for right-click so opening a context menu elsewhere also closes it. */ hideOnOutsideContextMenu(event) { const panel = this.popoverRef?.container; if (panel && !panel.contains(event.target)) { this.popoverRef.hide(); } } onSelectChange(formField) { formField.onChange(this.ctForm); setTimeout(() => this.popoverRef.align()); } /** * The signal-forms control→field binding is async, so a config `onChange` reading * `form.X().value()` would trail the handle. Sync the emitted value into the field first. */ onSliderValueChange(formField, value) { if (value === undefined) return; const fields = this.ctForm; fields[formField.name]?.().value.set(value); formField.onChange(this.ctForm); } /** Same async control→field gap as onSliderValueChange - the emitted checked state is * synced into the field before firing the config's onChange. */ onToggleChange(formField, checked) { const fields = this.ctForm; fields[formField.name]?.().value.set(checked); formField.onChange(this.ctForm); } resolveFieldBound(key, bound) { if (typeof bound !== 'function') return bound; if (!this.boundSignals.has(key)) { const boundFunction = bound; this.boundSignals.set(key, (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.computed)(() => boundFunction(this.ctForm))); } return this.boundSignals.get(key)?.() ?? 0; } static ɵfac = function SettingsPopoverComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SettingsPopoverComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: SettingsPopoverComponent, selectors: [["lib-settings-popover"]], viewQuery: function SettingsPopoverComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵviewQuery"](_c0, 5); } if (rf & 2) { let _t; _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵloadQuery"]()) && (ctx.popoverRef = _t.first); } }, hostBindings: function SettingsPopoverComponent_HostBindings(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("contextmenu", function SettingsPopoverComponent_contextmenu_HostBindingHandler($event) { return ctx.hideOnOutsideContextMenu($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵresolveDocument"]); } }, inputs: { buttonTooltip: [1, "buttonTooltip"], buttonAriaLabel: [1, "buttonAriaLabel"], title: [1, "title"], isDarkMode: [1, "isDarkMode"], formFieldConfig: [1, "formFieldConfig"], popoverTarget: [1, "popoverTarget"], showButton: [1, "showButton"], externalOpen: [1, "externalOpen"], draggable: [1, "draggable"], dragHandleAriaLabel: [1, "dragHandleAriaLabel"], dragBoundary: [1, "dragBoundary"] }, outputs: { visibilityChange: "visibilityChange", closed: "closed" }, decls: 11, vars: 4, consts: [["popover", ""], ["settingsButton", ""], ["tooltipPosition", "top", "iconType", "prime", "icon", "sliders-h", "iconClass", "text-lg", 3, "tooltip", "ariaLabel"], [3, "onHide", "onShow"], [1, "flex", "flex-col"], [1, "flex", "items-center", "justify-between", "gap-4", "px-3"], ["id", "ct-settings-title", 1, "text-color", "font-semibold"], ["data-test-id", "settings-popover-span-drag-handle", 1, "text-color", "flex", "cursor-move", "items-center", "opacity-70", "hover:opacity-100"], [1, "my-3"], [1, "flex", "flex-col", "gap-2"], ["tooltipPosition", "top", "iconType", "prime", "icon", "sliders-h", "iconClass", "text-lg", 3, "click", "tooltip", "ariaLabel"], ["data-test-id", "settings-popover-span-drag-handle", 1, "text-color", "flex", "cursor-move", "items-center", "opacity-70", "hover:opacity-100", 3, "mousedown"], ["icon", "arrows-alt", "iconType", "prime", "iconClass", "text-sm"], [1, "px-3", "py-2"], ["optionLabel", "label", "optionValue", "value", "fluid", "", "size", "small", 1, "mb-2", 3, "onChange", "formField", "options", "group", "ngClass", "placeholder"], ["pTemplate", "group"], ["pTemplate", "item"], ["pTemplate", "selectedItem"], [1, "align-items-center", "justify-content-between", "text-color", "flex", "text-sm", "font-semibold"], [1, "align-items-center", "flex", "w-full", "justify-between", "gap-2", "text-sm", 3, "innerHTML"], [1, "align-items-center", "flex", "w-full", "justify-between", "gap-2", 3, "innerHTML"], ["size", "small", "severity", "secondary", "styleClass", "w-full justify-center", 3, "onClick"], [1, "size-(--p-app-icon-size-xs)", 3, "icon"], [1, "text-xs"], ["fluid", "", "size", "small", 3, "onClick", "label", "disabled"], [3, "sliderValueChanged", "slideEnd", "resetClicked", "dragStart", "dragEnd", "label", "minValue", "maxValue", "step", "formField", "isDisabled", "tooltip", "showValue", "valueSuffix", "valueFormatter"], [1, "flex", "items-center", "justify-between", "gap-4", "px-3", "py-2"], [1, "text-sm", "text-white"], [3, "onChange", "inputId", "formField"]], template: function SettingsPopoverComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](0, SettingsPopoverComponent_Conditional_0_Template, 2, 2, "lib-viewport-button", 2); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](1, "p-popover", 3, 0); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵlistener"]("onHide", function SettingsPopoverComponent_Template_p_popover_onHide_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); ctx.visibilityChange.emit(true); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.closed.emit()); })("onShow", function SettingsPopoverComponent_Template_p_popover_onShow_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); ctx.visibilityChange.emit(false); ctx.resetPosition(); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.centerOverAnchor()); }); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](3, "div", 4)(4, "div", 5)(5, "h3", 6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtext"](6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](7, SettingsPopoverComponent_Conditional_7_Template, 2, 1, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelement"](8, "p-divider", 8); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementStart"](9, "div", 9); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditionalCreate"](10, SettingsPopoverComponent_Conditional_10_Template, 3, 0, "form"); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵelementEnd"]()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx.showButton() ? 0 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](6); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵtextInterpolate1"](" ", ctx.title(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx.draggable() ? 7 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵconditional"](ctx.initialized() ? 10 : -1); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_8__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_8__.Button, primeng_api__WEBPACK_IMPORTED_MODULE_18__.PrimeTemplate, _viewport_setting_slider_viewport_setting_slider_component__WEBPACK_IMPORTED_MODULE_17__.ViewportSettingSliderComponent, primeng_popover__WEBPACK_IMPORTED_MODULE_10__.Popover, primeng_divider__WEBPACK_IMPORTED_MODULE_9__.Divider, primeng_select__WEBPACK_IMPORTED_MODULE_11__.SelectModule, primeng_select__WEBPACK_IMPORTED_MODULE_11__.Select, primeng_toggleswitch__WEBPACK_IMPORTED_MODULE_12__.ToggleSwitch, _angular_forms_signals__WEBPACK_IMPORTED_MODULE_5__.FormField, _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_16__.ViewportButtonComponent, _icon_icon_component__WEBPACK_IMPORTED_MODULE_15__.IconComponent, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgClass, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_7__.TranslatePipe], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 80922 /*!****************************************************!*\ !*** ./libs/ui/src/lib/slider/slider.component.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SliderComponent: () => (/* binding */ SliderComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/forms */ 74381); /* harmony import */ var primeng_slider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/slider */ 31486); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 14975); class SliderComponent { sliderType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "sliderType" }] : [])); sliderChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); slideEnd = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); keyDown = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); mouseDown = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); mouseUp = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); sliderStep = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(1, ...(ngDevMode ? [{ debugName: "sliderStep" }] : [])); sliderOrientation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('horizontal', ...(ngDevMode ? [{ debugName: "sliderOrientation" }] : [])); // PrimeNG's own .p-slider CSS is `display: block` with no explicit width - as a flex/grid // child with no flex-grow of its own, that collapses to its (contentless) intrinsic size, // i.e. 0. w-full/min-w-0 must be part of the class list for the slider to size itself to // its container; callers that need something other than a full-width slider (e.g. // corner-sliders' fixed corner layout) already override this input explicitly. sliderClassName = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('w-full min-w-0 pointer-events-auto', ...(ngDevMode ? [{ debugName: "sliderClassName" }] : [])); isDisabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : [])); dataTestIdOverride = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "dataTestIdOverride" }] : [])); sliderMax = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(100, ...(ngDevMode ? [{ debugName: "sliderMax" }] : [])); sliderMin = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "sliderMin" }] : [])); name = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('slider', ...(ngDevMode ? [{ debugName: "name" }] : [])); startingValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(0, ...(ngDevMode ? [{ debugName: "startingValue" }] : [])); sliderValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(this.startingValue(), ...(ngDevMode ? [{ debugName: "sliderValue" }] : [])); sliderRef; boundsEffectRef; constructor() { this.boundsEffectRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.effect)(() => { const min = this.sliderMin(); const max = this.sliderMax(); (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.untracked)(() => { if (!this.sliderRef) return; this.sliderRef.min = min; this.sliderRef.max = max; this.sliderRef.updateHandleValue(); this.sliderRef.updateDiffAndOffset(); this.sliderRef.cd.markForCheck(); }); }, ...(ngDevMode ? [{ debugName: "boundsEffectRef" }] : [])); } ngOnDestroy() { this.boundsEffectRef.destroy(); } onSliderChange(value) { this.sliderValue.set(value); this.sliderChanged.emit(value); } onSliderEnd(event) { if (event.value === undefined) return; this.sliderValue.set(event.value); this.sliderChanged.emit(event.value); this.slideEnd.emit(event.value); } computedDataTestId() { const dataTestId = this.dataTestIdOverride(); if (dataTestId && dataTestId.trim() !== '') { return dataTestId; } return `slider-p-slider-${this.name()}`; } static ɵfac = function SliderComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SliderComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineComponent"]({ type: SliderComponent, selectors: [["lib-slider"]], viewQuery: function SliderComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵviewQuery"](primeng_slider__WEBPACK_IMPORTED_MODULE_3__.Slider, 5); } if (rf & 2) { let _t; _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵloadQuery"]()) && (ctx.sliderRef = _t.first); } }, inputs: { sliderType: [1, "sliderType"], sliderStep: [1, "sliderStep"], sliderOrientation: [1, "sliderOrientation"], sliderClassName: [1, "sliderClassName"], isDisabled: [1, "isDisabled"], dataTestIdOverride: [1, "dataTestIdOverride"], sliderMax: [1, "sliderMax"], sliderMin: [1, "sliderMin"], name: [1, "name"], startingValue: [1, "startingValue"], sliderValue: [1, "sliderValue"] }, outputs: { sliderChanged: "sliderChanged", slideEnd: "slideEnd", keyDown: "keyDown", mouseDown: "mouseDown", mouseUp: "mouseUp", sliderValue: "sliderValueChange" }, decls: 2, vars: 10, consts: [[1, "flex", "h-full", "min-h-0", "w-full", "min-w-0", "items-center"], [3, "ngModelChange", "onSlideEnd", "keydown", "mousedown", "mouseup", "ngModel", "min", "max", "name", "step", "disabled", "orientation"]], template: function SliderComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementStart"](0, "div", 0)(1, "p-slider", 1); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtwoWayListener"]("ngModelChange", function SliderComponent_Template_p_slider_ngModelChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtwoWayBindingSet"](ctx.sliderValue, $event) || (ctx.sliderValue = $event); return $event; }); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵlistener"]("ngModelChange", function SliderComponent_Template_p_slider_ngModelChange_1_listener($event) { return ctx.onSliderChange($event); })("onSlideEnd", function SliderComponent_Template_p_slider_onSlideEnd_1_listener($event) { return ctx.onSliderEnd($event); })("keydown", function SliderComponent_Template_p_slider_keydown_1_listener($event) { return ctx.keyDown.emit($event); })("mousedown", function SliderComponent_Template_p_slider_mousedown_1_listener($event) { return ctx.mouseDown.emit($event); })("mouseup", function SliderComponent_Template_p_slider_mouseup_1_listener($event) { return ctx.mouseUp.emit($event); })("mouseup", function SliderComponent_Template_p_slider_mouseup_1_listener($event) { return ctx.mouseUp.emit($event); }, _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵresolveWindow"]); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵclassMap"](ctx.sliderClassName()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵtwoWayProperty"]("ngModel", ctx.sliderValue); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵproperty"]("min", ctx.sliderMin())("max", ctx.sliderMax())("name", ctx.name())("step", ctx.sliderStep())("disabled", ctx.isDisabled())("orientation", ctx.sliderOrientation()); _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵattribute"]("data-test-id", ctx.computedDataTestId()); } }, dependencies: [primeng_slider__WEBPACK_IMPORTED_MODULE_3__.SliderModule, primeng_slider__WEBPACK_IMPORTED_MODULE_3__.Slider, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.FormsModule, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgControlStatus, _angular_forms__WEBPACK_IMPORTED_MODULE_2__.NgModel], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 93742 /*!**************************************************!*\ !*** ./libs/ui/src/lib/table/table.component.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TableComponent: () => (/* binding */ TableComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_menu__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/menu */ 64204); /* harmony import */ var primeng_table__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! primeng/table */ 70213); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _menu_item_menu_item_component__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../menu-item/menu-item.component */ 94222); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/core */ 14975); function TableComponent_ng_template_2_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "th", 5); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "p-tableHeaderCheckbox"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } } function TableComponent_ng_template_2_For_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "th", 6); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const col_r2 = ctx.$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("id", _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵinterpolate"](col_r2.field)); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", ctx_r2.getLabel(col_r2.field, "columns"), " "); } } function TableComponent_ng_template_2_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "th", 7); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", ctx_r2.getLabel("actions", "columns"), " "); } } function TableComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "tr"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](1, TableComponent_ng_template_2_Conditional_1_Template, 2, 0, "th", 5); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterCreate"](2, TableComponent_ng_template_2_For_3_Template, 2, 3, "th", 6, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](4, TableComponent_ng_template_2_Conditional_4_Template, 2, 1, "th", 7); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const columns_r4 = ctx.$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](ctx_r2.allowRowSelection() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeater"](columns_r4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](ctx_r2.actions() && ctx_r2.actions().length > 0 ? 4 : -1); } } function TableComponent_ng_template_4_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "td", 9); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "p-tableCheckbox", 11); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("value", rowData_r6); } } function TableComponent_ng_template_4_For_3_Case_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipe"](1, "dicomPersonName"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipe"](2, "orDash"); } if (rf & 2) { const col_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipeBind1"](2, 3, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipeBind1"](1, 1, rowData_r6[col_r7.field])), " "); } } function TableComponent_ng_template_4_For_3_Case_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipe"](1, "dicomDate"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipe"](2, "orDash"); } if (rf & 2) { const col_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipeBind1"](2, 3, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipeBind1"](1, 1, rowData_r6[col_r7.field])), " "); } } function TableComponent_ng_template_4_For_3_Case_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](0); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipe"](1, "orDash"); } if (rf & 2) { const col_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate1"](" ", _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵpipeBind1"](1, 1, rowData_r6[col_r7.field]), " "); } } function TableComponent_ng_template_4_For_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "td"); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](1, TableComponent_ng_template_4_For_3_Case_1_Template, 3, 5)(2, TableComponent_ng_template_4_For_3_Case_2_Template, 3, 5)(3, TableComponent_ng_template_4_For_3_Case_3_Template, 2, 3); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_17_0; const col_r7 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"]((tmp_17_0 = col_r7.format) === "dicomPersonName" ? 1 : tmp_17_0 === "dicomDate" ? 2 : 3); } } function TableComponent_ng_template_4_Conditional_4_Conditional_1_ng_template_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](0, "lib-menu-item", 16); } if (rf & 2) { const item_r9 = ctx.$implicit; _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("item", item_r9); } } function TableComponent_ng_template_4_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "p-menu", 13, 2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtemplate"](2, TableComponent_ng_template_4_Conditional_4_Conditional_1_ng_template_2_Template, 1, 1, "ng-template", null, 3, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](4, "p-button", 14); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function TableComponent_ng_template_4_Conditional_4_Conditional_1_Template_p_button_click_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r8); const multiMenu_r10 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵreference"](1); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](multiMenu_r10.toggle($event)); })("keydown.enter", function TableComponent_ng_template_4_Conditional_4_Conditional_1_Template_p_button_keydown_enter_4_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r8); const multiMenu_r10 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵreference"](1); $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](multiMenu_r10.toggle($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](5, "lib-icon", 15); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const rowIndex_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](2).rowIndex; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("model", ctx_r2.multiSelectMenuItems())("popup", true); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵattribute"]("data-test-id", `table-p-menu-multi-select-menu-${rowIndex_r11}`); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵattribute"]("data-test-id", `table-p-button-multi-select-menu-${rowIndex_r11}`); } } function TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "span", 20); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const action_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"]().$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtextInterpolate"](ctx_r2.getLabel(action_r13.labelKey, "actions")); } } function TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) { const _r12 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "p-button", 18); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Template_p_button_click_0_listener($event) { const action_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r12).$implicit; const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](3).$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](action_r13.callback([rowData_r6])); })("keydown.enter", function TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Template_p_button_keydown_enter_0_listener($event) { const action_r13 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r12).$implicit; const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](3).$implicit; $event.stopPropagation(); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](action_r13.callback([rowData_r6])); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelement"](1, "lib-icon", 19); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](2, TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Conditional_2_Template, 2, 1, "span", 20); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const action_r13 = ctx.$implicit; const rowIndex_r11 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](3).rowIndex; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("styleClass", "p-0 hover:bg-transparent " + (action_r13.styleClass ?? "text-inherit"))("pTooltip", action_r13.showLabel ? "" : ctx_r2.getLabel(action_r13.labelKey, "actions")); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵattribute"]("data-test-id", `table-p-button-action-${action_r13.labelKey}-${rowIndex_r11}`); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵclassMap"](action_r13.styleClass ?? ""); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("icon", action_r13.icon); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](action_r13.showLabel ? 2 : -1); } } function TableComponent_ng_template_4_Conditional_4_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterCreate"](1, TableComponent_ng_template_4_Conditional_4_Conditional_2_For_2_Template, 3, 7, "p-button", 17, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeater"](ctx_r2.actions()); } } function TableComponent_ng_template_4_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "td", 10); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](1, TableComponent_ng_template_4_Conditional_4_Conditional_1_Template, 6, 4)(2, TableComponent_ng_template_4_Conditional_4_Conditional_2_Template, 3, 0, "div", 12); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](ctx_r2.selectedRowData().length > 1 ? 1 : 2); } } function TableComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "tr", 8); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵlistener"]("click", function TableComponent_ng_template_4_Template_tr_click_0_listener() { const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.handleRowClick(rowData_r6)); })("keydown.enter", function TableComponent_ng_template_4_Template_tr_keydown_enter_0_listener() { const rowData_r6 = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r5).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"](ctx_r2.handleRowClick(rowData_r6)); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](1, TableComponent_ng_template_4_Conditional_1_Template, 2, 1, "td", 9); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterCreate"](2, TableComponent_ng_template_4_For_3_Template, 4, 1, "td", null, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditionalCreate"](4, TableComponent_ng_template_4_Conditional_4_Template, 3, 1, "td", 10); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"](); } if (rf & 2) { const rowData_r6 = ctx.$implicit; const columns_r14 = ctx.columns; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵnextContext"](); const isLoading_r15 = ctx_r2.isRowLoading(rowData_r6); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵclassProp"]("active-row", ctx_r2.activeRow() === rowData_r6)("bg-primary-500/10", ctx_r2.activeRow() === rowData_r6)("border-l-2", ctx_r2.activeRow() === rowData_r6)("border-primary-500", ctx_r2.activeRow() === rowData_r6)("opacity-50", isLoading_r15)("pointer-events-none", isLoading_r15); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](ctx_r2.allowRowSelection() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵrepeater"](columns_r14); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵconditional"](ctx_r2.actions() && ctx_r2.actions().length > 0 ? 4 : -1); } } class TableComponent { translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_3__.TranslateService); columns = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "columns" }] : [])); rowData = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "rowData" }] : [])); translationRoot = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "translationRoot" }] : [])); allowRowSelection = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, { ...(ngDevMode ? { debugName: "allowRowSelection" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_0__.booleanAttribute }); actions = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)([], ...(ngDevMode ? [{ debugName: "actions" }] : [])); rowKey = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "rowKey" }] : [])); loadingRowKeys = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(new Set(), ...(ngDevMode ? [{ debugName: "loadingRowKeys" }] : [])); selectedRowData = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)([], ...(ngDevMode ? [{ debugName: "selectedRowData" }] : [])); activeRow = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.signal)(undefined, ...(ngDevMode ? [{ debugName: "activeRow" }] : [])); rowClicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); handleRowClick(row) { this.activeRow.set(row); this.rowClicked.emit(row); if (this.allowRowSelection()) { const current = this.selectedRowData(); const index = current.indexOf(row); this.selectedRowData.set(index === -1 ? [...current, row] : current.filter((_, index_) => index_ !== index)); } } multiSelectMenuItems = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.computed)(() => this.actions().map(action => ({ command: () => action.callback(this.selectedRowData()), icon: action.icon, label: this.getLabel(action.labelKey, 'actions') })), ...(ngDevMode ? [{ debugName: "multiSelectMenuItems" }] : [])); isRowLoading(row) { const key = this.rowKey(); return !!key && this.loadingRowKeys().has(row[key]); } getLabel(labelKey, labelType) { return this.translate.instant(`${this.translationRoot()}.table.${labelType}.${labelKey}`); } static ɵfac = function TableComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TableComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵdefineComponent"]({ type: TableComponent, selectors: [["lib-table"]], inputs: { columns: [1, "columns"], rowData: [1, "rowData"], translationRoot: [1, "translationRoot"], allowRowSelection: [1, "allowRowSelection"], actions: [1, "actions"], rowKey: [1, "rowKey"], loadingRowKeys: [1, "loadingRowKeys"], selectedRowData: [1, "selectedRowData"] }, outputs: { selectedRowData: "selectedRowDataChange", rowClicked: "rowClicked" }, decls: 6, vars: 3, consts: [["header", ""], ["body", ""], ["multiMenu", ""], ["item", ""], [3, "selectionChange", "columns", "value", "selection"], ["id", "selectionCheckBox", "pFrozenColumn", ""], [3, "id"], ["id", "actions"], [1, "cursor-pointer", "transition-colors", "duration-150", 3, "click", "keydown.enter"], ["pFrozenColumn", ""], ["className", "pl-0 pr-0 text-primary-500"], [3, "value"], [1, "flex"], ["appendTo", "body", 3, "model", "popup"], ["variant", "text", "styleClass", "p-0 text-inherit hover:bg-transparent", "size", "small", 3, "click", "keydown.enter"], ["icon", "ellipsis-v", "iconClass", "size-(--p-app-icon-size-sm)"], [3, "item"], ["variant", "text", "size", "small", "tooltipPosition", "left", 3, "styleClass", "pTooltip"], ["variant", "text", "size", "small", "tooltipPosition", "left", 3, "click", "keydown.enter", "styleClass", "pTooltip"], ["iconClass", "size-(--p-app-icon-size-sm)", 3, "icon"], [1, "ml-1", "text-sm"]], template: function TableComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementStart"](0, "div")(1, "p-table", 4); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtwoWayListener"]("selectionChange", function TableComponent_Template_p_table_selectionChange_1_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵrestoreView"](_r1); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtwoWayBindingSet"](ctx.selectedRowData, $event) || (ctx.selectedRowData = $event); return _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵresetView"]($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtemplate"](2, TableComponent_ng_template_2_Template, 5, 2, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtemplateRefExtractor"])(4, TableComponent_ng_template_4_Template, 5, 14, "ng-template", null, 1, _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtemplateRefExtractor"]); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵproperty"]("columns", ctx.columns())("value", ctx.rowData()); _angular_core__WEBPACK_IMPORTED_MODULE_11__["ɵɵtwoWayProperty"]("selection", ctx.selectedRowData); } }, dependencies: [primeng_table__WEBPACK_IMPORTED_MODULE_6__.TableModule, primeng_table__WEBPACK_IMPORTED_MODULE_6__.Table, primeng_table__WEBPACK_IMPORTED_MODULE_6__.FrozenColumn, primeng_table__WEBPACK_IMPORTED_MODULE_6__.TableCheckbox, primeng_table__WEBPACK_IMPORTED_MODULE_6__.TableHeaderCheckbox, _icon_icon_component__WEBPACK_IMPORTED_MODULE_9__.IconComponent, primeng_button__WEBPACK_IMPORTED_MODULE_4__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_4__.Button, primeng_menu__WEBPACK_IMPORTED_MODULE_5__.MenuModule, primeng_menu__WEBPACK_IMPORTED_MODULE_5__.Menu, primeng_tooltip__WEBPACK_IMPORTED_MODULE_7__.Tooltip, _menu_item_menu_item_component__WEBPACK_IMPORTED_MODULE_10__.MenuItemComponent, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.DicomDatePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.DicomPersonNamePipe, _tomoverse_utils__WEBPACK_IMPORTED_MODULE_8__.OrDashPipe], encapsulation: 2 }); } /***/ }, /***/ 94644 /*!**************************************************!*\ !*** ./libs/ui/src/lib/table/table.constants.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PRIMENG_DEFAULT_SORT_ORDER: () => (/* binding */ PRIMENG_DEFAULT_SORT_ORDER) /* harmony export */ }); /** * PrimeNG's own default for the `p-table` `sortOrder` input (ascending). Use it as the * fallback when no sort is active: with `sortField` unset the table does not sort, * so it only exists because the input is typed as `number`. */ const PRIMENG_DEFAULT_SORT_ORDER = 1; /***/ }, /***/ 29904 /*!*********************************************!*\ !*** ./libs/ui/src/lib/theme/app-tokens.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationHexColors: () => (/* binding */ annotationHexColors), /* harmony export */ annotationPaletteHexColors: () => (/* binding */ annotationPaletteHexColors), /* harmony export */ appColorTokens: () => (/* binding */ appColorTokens), /* harmony export */ appScaleTokens: () => (/* binding */ appScaleTokens), /* harmony export */ fullPickerPaletteHexColors: () => (/* binding */ fullPickerPaletteHexColors), /* harmony export */ pickerPaletteHexColors: () => (/* binding */ pickerPaletteHexColors) /* harmony export */ }); /** * Mirror of the Figma variable collection, plus clearly marked proposed * additions and app-only aliases Figma does not carry yet. Emitted under * the single `app` namespace (`--p-app-*`) via extend.ts. * * This is the only file where color/scale literals may live. Everything else * consumes `--p-app-*` vars or `{app.*}` refs (enforced by lint:colors). * Non-CSS consumers (VTK, Cornerstone) cannot resolve var() refs, they * import the exported hex constants below instead. * * Rules: keys are kebab-case and alphabetical, aliases use `{app.*}` refs. */ /** * Raw hex for the protocol annotation colors, exported for non-CSS consumers. * Annotation color data feeds parseHexColor and VTK actors, which cannot * resolve var() refs. The `annotation` token group spreads this map, so CSS * and persisted data stay on the same Figma values. */ const annotationHexColors = { annulus: '#ffc100', artifacts: '#009688', commissure: '#9575cd', 'coronary-height-left': '#c62828', 'coronary-height-right': '#4caf50', lvot: '#cddc39', 'nadir-lcc': '#ff0000', 'nadir-ncc': '#2196f3', 'nadir-rcc': '#8bc34a', 'quality-check': '#ff9800', 'sinus-point': '#ff00ff', sov: '#6d7fe3', stj: '#ff5722' }; /** * Ordered annotation color palettes, exported as arrays because order is * meaningful (assignment rotation and picker layout). Values keep their * original casing because annotations persist these exact strings. Same * non-CSS consumers as annotationHexColors. Emitted as numbered * `app.palette.*` tokens below so the theme-preview gallery shows them. */ const annotationPaletteHexColors = ['#459CED', '#FBE94E', '#CF335A', '#CAD748', '#ED932B', '#4288EB', '#F3BC34', '#8DBA4D', '#CB69EE', '#4DB0CB', '#E85A2E', '#5EA34E', '#8765D9', '#DB4A38', '#3C897D', '#6573D9']; const pickerPaletteHexColors = ['#DB4A38', '#CF335A', '#CB69EE', '#8765D9', '#6573D9', '#4288EB', '#459CED', '#4DB0CB', '#E85A2E', '#ED932B', '#F3BC34', '#FBE94E', '#CAD748', '#8DBA4D', '#5EA34E', '#3C897D']; const fullPickerPaletteHexColors = ['#EC8B2A', '#F1AE30', '#F5C63F', '#F9DD81', '#FDF7DF', '#AC322A', '#CB4136', '#D7554C', '#DE9491', '#FBE9EC', '#561E8B', '#7229B7', '#9739F0', '#BB72FF', '#E0C0FF', '#F108F1', '#FF50FF', '#FF7DFF', '#FFA8FF', '#FFDAFF', '#4288EB', '#65A5FF', '#93C0FF', '#B0D1FF', '#D3E5FF', '#82C81F', '#A1E93A', '#C1FF69', '#D6FF9C', '#ECFFD1', '#EA184C', '#FF537E', '#FF86A4', '#FFB0C4', '#FFDDE5']; const numbered = colors => Object.fromEntries(colors.map((color, index) => [String(index + 1), color])); const appColorTokens = { accent: { deep: '#f59e0b' }, action: { destructive: '{app.red.500}', 'destructive-background': 'color-mix(in srgb, {app.red.500} 16%, transparent)', 'primary-icon': '{app.amber.400}', 'primary-label': '{app.neutral.100}' }, amber: { '400': '#fbbf24' }, annotation: { ...annotationHexColors, comments: '{app.annotation.annulus}', variant: '{app.annotation.sov}' }, blue: { '500': '#3b82f6' }, border: { panel: '#2f2f33', strong: '{app.neutral.700}', subtle: '{app.neutral.800}' }, chip: { fill: '#1d1d20' }, chrome: { 'app-header': '{app.neutral.900}', 'info-block': 'color-mix(in srgb, {app.chrome.app-header} 60%, transparent)', 'page-header': 'color-mix(in srgb, {app.chrome.app-header} 80%, transparent)' }, // Figma light-content set, kept as-is. NOT the PrimeNG semantic // `--p-content-*` tokens, which resolve dark in the dark scheme. Do not use // these on dark-scheme surfaces. content: { background: '#ffffff', border: '{app.slate.200}', 'hover-background': '{app.slate.100}', text: '{app.slate.700}', 'text-muted': '{app.slate.500}', 'text-secondary': '{app.neutral.400}' }, cpr: { cursor: '{app.amber.400}', 'cut-line': '{app.amber.400}', label: '#ffffff', 'node-fallback': '#ffffff', seam: '{app.amber.400}', tick: '{app.neutral.500}' }, // The `dark-*` names come from Figma, where "dark" describes the // one existing scheme. They are emitted in both schemes like every other // app token, so they will need renaming or light values when a light scheme // is designed. 'dark-border': '{app.neutral.800}', 'dark-overlay-modal': '{app.neutral.700}', 'dark-surface-base': '{app.neutral.950}', 'dark-surface-hover': '{app.neutral.800}', 'dark-surface-raised': '{app.neutral.900}', 'dark-surface-row': '{app.neutral.950}', 'dark-surface-selected': '{app.neutral.800}', 'dark-text': '{app.neutral.50}', 'dark-text-muted': '{app.neutral.200}', emerald: { '50': '#ecfdf5', '500': '#10b981', '700': '#047857' }, graph: { axis: '#ffffff', background: '#000000', grid: '{app.neutral.700}', label: '#ffffff' }, green: { '500': '#22c55e' }, input: { border: '{app.neutral.600}', 'recessed-bg': '{app.neutral.950}' }, label: { proposed: '#c9a227' }, modality: { fill: '{app.neutral.800}', text: '{app.neutral.300}' }, neutral: { '100': '#f4f4f5', '200': '#e4e4e7', '300': '#d4d4d8', '400': '#a1a1aa', '50': '#fafafa', '500': '#71717a', '600': '#52525b', '700': '#3f3f46', '800': '#27272a', '900': '#18181b', '950': '#09090b' }, palette: { annotation: numbered(annotationPaletteHexColors), picker: numbered(pickerPaletteHexColors), 'picker-full': numbered(fullPickerPaletteHexColors) }, phase: { 'active-background': '{app.state.active-phase-background}', 'active-color': '{app.dark-text}', 'active-item-background': '{app.state.active-phase-item-background}' }, primary: { base: '#d9aa00', 'brand-gradient-from': '#ffd640', 'brand-gradient-to': '{app.primary.base}', 'selected-background': '{app.emerald.50}', 'selected-text': '{app.emerald.700}' }, red: { '500': '#ef4444' }, review: { approved: '{app.green.500}', 'approved-background': 'color-mix(in srgb, {app.green.500} 10%, transparent)', none: '{app.neutral.600}', pending: '{app.neutral.500}', rejected: '{app.red.500}' }, ring: { color: '{app.amber.400}' }, section: { annotation: '#f59e0b', chamber: '{app.blue.500}', contrast: '#ffffff', 'planar-reformation': '#14b8a6', protocol: '#a855f7', scan: '{app.green.500}', scurve: '#ec4899' }, slate: { '100': '#f1f5f9', '200': '#e2e8f0', '300': '#cbd5e1', '400': '#94a3b8', '50': '#f8fafc', '500': '#64748b', '600': '#475569', '700': '#334155', '800': '#1e293b', '900': '#0f172a', '950': '#020617' }, state: { 'active-phase-background': '{app.neutral.800}', 'active-phase-item-background': '{app.chip.fill}' }, status: { danger: '{app.action.destructive}', 'danger-background': '{app.action.destructive-background}', success: '{app.review.approved}', 'success-background': '{app.review.approved-background}' }, surface: { card: '#141416', 'card-hover': 'color-mix(in srgb, {app.surface.card} 55%, {app.neutral.800})', 'icon-holder': '#171717', modal: '{app.neutral.900}', tab: '{app.neutral.800}', table: '{app.neutral.900}' }, viewport: { 'axis-axial': '#00FF00', 'axis-coronal': '#0000FF', 'axis-sagittal': '#FF0000', background: '#000000', indicator: { axial: '{app.viewport.marker-1}', coronal: '{app.viewport.marker-2}', sagittal: '{app.viewport.marker-3}' }, label: '#ffffff', 'marker-1': '{app.green.500}', 'marker-2': '{app.blue.500}', 'marker-3': '{app.red.500}', 'maximized-crosshair': '{app.accent.deep}', outline: '#000000' } }; const appScaleTokens = { family: { base: "'Inter var', Inter, ui-sans-serif, system-ui, sans-serif" }, 'font-size': { lg: '20px', md: '16px', sm: '14px', xl: '24px', xs: '12px' }, 'font-weight': { bold: '700', medium: '500', regular: '400', semibold: '600' }, 'icon-size': { md: '24px', sm: '20px', xs: '16px', xxs: '12px', xxxs: '9px' }, 'line-height': { normal: '1.5', tight: '1.25' }, // The semantic names (base, card, chip, control, overlay) alias the size // scale so equal Figma values stay single-sourced. radius: { base: '{app.radius.md}', card: '{app.radius.md}', chip: '{app.radius.full}', control: '{app.radius.md}', full: '9999px', lg: '8px', md: '6px', overlay: '{app.radius.xl}', sm: '4px', xl: '12px', xs: '2px' }, ring: { offset: '2px', style: 'solid', width: '1px' }, sidebar: { width: '300px' }, spacing: { '1': '4px', '2': '8px', '3': '12px', '4': '16px', '5': '20px', '6': '24px', '8': '32px' } }; /***/ }, /***/ 48512 /*!*********************************************!*\ !*** ./libs/ui/src/lib/theme/components.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ components: () => (/* binding */ components) /* harmony export */ }); /* harmony import */ var _menu_item_classes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./menu-item-classes */ 3730); const dangerSurface = red => `color-mix(in srgb, ${red} 16%, transparent)`; const dangerMenuItemCss = (dt, prefix) => ` .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS} > .${prefix}-item-content .${prefix}-item-link, .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS} > .${prefix}-item-content .${prefix}-item-icon { color: ${dt('red.400')}; } .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}:not(.p-disabled) > .${prefix}-item-content:hover, .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}.p-focus > .${prefix}-item-content { background: ${dangerSurface(dt('red.500'))}; } .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}:not(.p-disabled) > .${prefix}-item-content:hover .${prefix}-item-link, .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}:not(.p-disabled) > .${prefix}-item-content:hover .${prefix}-item-icon, .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}.p-focus > .${prefix}-item-content .${prefix}-item-link, .${prefix}-item.${_menu_item_classes__WEBPACK_IMPORTED_MODULE_0__.DANGER_MENU_ITEM_CLASS}.p-focus > .${prefix}-item-content .${prefix}-item-icon { color: ${dt('red.300')}; } `; /** * Gap between a trigger and its overlay panel. Popover gets it via its * `gutter` token, which PrimeNG applies direction-aware. The other overlays * have no such token, so they get a plain margin-top. Known trade-off: when * an overlay flips above its trigger (trigger near the viewport bottom), the * margin shifts it 4px toward the trigger instead of away. */ const OVERLAY_GAP = '4px'; const overlayGapCss = selector => ` ${selector} { margin-top: ${OVERLAY_GAP}; } `; /** * Keeps menu overlays on their own compositing layer for as long as they exist. * * PrimeNG animates these overlays in (@primeuix/motion), which promotes them to a * temporary layer; when that layer is torn down on animation end, Chromium in * Electron can fail to repaint the icon-font glyphs. */ const glyphPaintCss = selector => ` ${selector} { will-change: transform; } `; const listScrollbarCss = (dt, container) => ` ${container} { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, ${dt('surface.500')} 45%, transparent) transparent; } `; /** * Component-level token overrides. * * COLORS are intentionally absent: component colors are stock Aura (resolved * against the amber/zinc semantic layer), matching the reference design. Only * scheme-invariant tokens (padding, sizes, radii, layout css) and app-feature * css (danger menu items, active store) belong here. A color override, when * one is truly needed, must sit under the component's `colorScheme.dark` / * `colorScheme.light` with both schemes populated. */ const components = { accordion: { header: { padding: '0.5rem' } }, button: { colorScheme: { dark: { outlined: { contrast: { borderColor: '{surface.700}', color: '{surface.100}' } }, text: { plain: { color: '{surface.300}' } } }, // TODO: design stock Aura light placeholders, keep keys symmetric with `dark`. light: { outlined: { contrast: { borderColor: '{surface.700}', color: '{surface.950}' } }, text: { plain: { color: '{surface.700}' } } } } }, contextmenu: { css: options => ` ${glyphPaintCss('.p-contextmenu')} ${dangerMenuItemCss(options.dt, 'p-contextmenu')} ` }, datatable: { bodyCell: { padding: '0.5rem 0.75rem' }, colorScheme: { dark: { bodyCell: { selectedBorderColor: '{surface.900}' }, headerCell: { background: '{surface.900}', selectedBackground: '{surface.800}', selectedColor: '{text.color}' }, // Not redundant: Aura defaults rows to {content.background} row: { background: 'transparent' } }, // TODO: design stock Aura light placeholders, keep keys symmetric with `dark`. light: { bodyCell: { selectedBorderColor: '{surface.900}' }, headerCell: { background: '{surface.900}', selectedBackground: '{surface.800}', selectedColor: '{text.color}' }, row: { background: 'transparent' } } }, css: ` /* Scrollable tables paint the whole sticky thead with the header-cell background; keep the background on the header cells only, so extra header rows (e.g. the filter row) can stay transparent. */ .p-datatable-scrollable > .p-datatable-table-container > .p-datatable-table > .p-datatable-thead, .p-datatable-scrollable > .p-datatable-table-container > .p-virtualscroller > .p-datatable-table > .p-datatable-thead { background: transparent; } /* Safety net: fixed-width column headers must never bleed into their neighbor. Plain-text headers also get a free ellipsis; headers whose content is a flex-wrapped label + sort icon still need their own inner min-w-0/truncate span for a real ellipsis, since text-overflow doesn't apply inside flex containers - this only guarantees a clip. */ .p-datatable-thead > tr > th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .p-datatable-thead > tr > th > span { display: inline-flex; overflow: hidden; min-width: 0; max-width: 100%; } `, headerCell: { padding: '0.5rem 0.75rem' } }, datepicker: { css: () => overlayGapCss('.p-datepicker-panel:not(.p-datepicker-panel-inline)') }, drawer: { colorScheme: { dark: { root: { background: '{surface.900}', borderColor: '{app.border.panel}', color: '{surface.50}' } }, // TODO: design stock Aura light placeholders, keep keys symmetric with `dark`. light: { root: { background: '{overlay.modal.background}', borderColor: '{overlay.modal.border.color}', color: '{overlay.modal.color}' } } }, title: { fontWeight: 'medium' } }, menu: { css: options => ` ${overlayGapCss('.p-menu-overlay')} ${glyphPaintCss('.p-menu')} .p-menu .active-store .p-menu-item-link, .p-menu .active-store .p-menu-item-icon { color: ${options.dt('primary.400')}; } .p-menu .active-store .p-menu-item-content:hover .p-menu-item-link, .p-menu .active-store.p-focus .p-menu-item-link { color: inherit; } ${dangerMenuItemCss(options.dt, 'p-menu')} ` }, multiselect: { css: options => ` ${overlayGapCss('.p-multiselect-overlay')} ${listScrollbarCss(options.dt, '.p-multiselect-list-container')} ` }, panel: { colorScheme: { dark: { root: { background: '{app.chrome.info-block}', borderColor: '{app.border.subtle}', color: '{surface.50}' } }, // TODO: design stock Aura light placeholders, keep keys symmetric with `dark`. light: { root: { background: '{content.background}', borderColor: '{content.border.color}', color: '{text.color}' } } }, content: { padding: '1.0625rem' }, root: { borderRadius: '{border.radius.lg}' } }, popover: { css: `.p-popover:before, .p-popover:after { content: none; }`, root: { borderRadius: '{border.radius.xl}', gutter: OVERLAY_GAP } }, select: { css: options => ` ${overlayGapCss('.p-select-overlay')} ${listScrollbarCss(options.dt, '.p-select-list-container')} ` }, slider: { colorScheme: { dark: { handle: { background: '{primary.color}', content: { background: '{primary.color}', hoverBackground: '{primary.hoverColor}' }, hoverBackground: '{primary.color}' }, track: { background: '{surface.300}' } }, // TODO: design. Placeholder values, keep keys symmetric with `dark`. light: { handle: { background: '{primary.color}', content: { background: '{surface.300}', hoverBackground: '{surface.0}' }, hoverBackground: '{primary.color}' }, track: { background: '{surface.300}' } } }, css: options => ` /* Extends the track's clickable area beyond its visible bounds. */ .p-slider-horizontal::before { content: ''; position: absolute; inset-block: -0.5rem; inset-inline: 0; } .p-slider-vertical::before { content: ''; position: absolute; inset-inline: -0.5rem; inset-block: 0; } /* The focus ring is suppressed below. Keyboard focus shows the same handle reaction as pointer hover/drag instead. */ .p-slider:not(.p-disabled) .p-slider-handle:focus-visible { background: ${options.dt('slider.handle.hover.background')}; } .p-slider:not(.p-disabled) .p-slider-handle:focus-visible::before { background: ${options.dt('slider.handle.content.hover.background')}; } `, handle: { focusRing: { color: 'transparent', shadow: 'none', width: '0' } } }, splitter: { css: options => { return ` .p-splitter { border:none; } .p-splitter-gutter:hover { background: ${options.dt('primary.400')}; } .p-splitter-gutter-handle { width: 0.125rem !important; } .p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle { height: 0.125rem !important; } `; }, handle: { size: '100%' } }, tabs: { colorScheme: { dark: { tab: { background: '{app.surface.tab}', hoverBackground: '{app.surface.tab}' } }, // TODO: design stock Aura light placeholders, keep keys symmetric with `dark`. light: { tab: { background: '{app.surface.tab}', hoverBackground: '{app.surface.tab}' } } } }, tag: { root: { fontSize: '0.75rem', fontWeight: 'normal', padding: '0.2rem 0.4rem' } } }; /***/ }, /***/ 59840 /*!*****************************************!*\ !*** ./libs/ui/src/lib/theme/extend.ts ***! \*****************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extend: () => (/* binding */ extend) /* harmony export */ }); /* harmony import */ var _app_tokens__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./app-tokens */ 29904); /** * Single design-token namespace, emitted as `--p-app-*` CSS variables. * * All values (literals and `{app.*}` aliases) live in app-tokens.ts. This * file only wires them into the preset and must stay literal-free (enforced * by scripts/check-color-tokens.mjs). * * Both schemes share the same values: Figma has only a dark mode so far, * and the clinical viewport/CPR tokens are drawn over the medical image and * intentionally never change with the UI scheme. */ const extend = { app: _app_tokens__WEBPACK_IMPORTED_MODULE_0__.appScaleTokens, colorScheme: { dark: { app: _app_tokens__WEBPACK_IMPORTED_MODULE_0__.appColorTokens }, light: { app: _app_tokens__WEBPACK_IMPORTED_MODULE_0__.appColorTokens } } }; /***/ }, /***/ 3730 /*!****************************************************!*\ !*** ./libs/ui/src/lib/theme/menu-item-classes.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DANGER_MENU_ITEM_CLASS: () => (/* binding */ DANGER_MENU_ITEM_CLASS), /* harmony export */ dangerMenuItem: () => (/* binding */ dangerMenuItem) /* harmony export */ }); /** * Marks a destructive item in a `p-menu` or `p-contextmenu`. Not part of the public * surface: reach it through {@link dangerMenuItem}. The PrimeNG preset is the only other * consumer, and it owns the colours, including the hover and focus states. */ const DANGER_MENU_ITEM_CLASS = 'danger-menu-item'; const dangerMenuItem = item => ({ ...item, styleClass: DANGER_MENU_ITEM_CLASS }); /***/ }, /***/ 80036 /*!*************************************************!*\ !*** ./libs/ui/src/lib/theme/primeng-preset.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ThemePreset: () => (/* binding */ ThemePreset) /* harmony export */ }); /* harmony import */ var _primeuix_themes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @primeuix/themes */ 2581); /* harmony import */ var _primeuix_themes_aura__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @primeuix/themes/aura */ 20719); /* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components */ 48512); /* harmony import */ var _extend__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./extend */ 59840); /* harmony import */ var _semantic__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./semantic */ 20168); /** * The app's design tokens, the single source of truth for every UI color. * * - `primitive`: Aura primitives repointed at the Figma tokens where values overlap * - `semantic`: scheme-dependent semantic tokens (surfaces, text, form fields) * - `components`: PrimeNG component-level overrides * - `extend`: app-specific tokens emitted as `--p-app-*` variables * * Colors change here, nowhere else. Component styles and templates must * reference tokens (`var(--p-…)` / token-backed Tailwind utilities), never * literal colors. */ const ThemePreset = (0,_primeuix_themes__WEBPACK_IMPORTED_MODULE_0__.definePreset)(_primeuix_themes_aura__WEBPACK_IMPORTED_MODULE_1__["default"], { components: _components__WEBPACK_IMPORTED_MODULE_2__.components, extend: _extend__WEBPACK_IMPORTED_MODULE_3__.extend, primitive: { borderRadius: { lg: '{app.radius.lg}', md: '{app.radius.md}', none: '0', sm: '{app.radius.sm}', xl: '{app.radius.xl}', xs: '{app.radius.xs}' } }, semantic: _semantic__WEBPACK_IMPORTED_MODULE_4__.semantic }); /***/ }, /***/ 57414 /*!*********************************************!*\ !*** ./libs/ui/src/lib/theme/provide-ui.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ provideUI: () => (/* binding */ provideUI) /* harmony export */ }); /* harmony import */ var primeng_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! primeng/config */ 32999); /* harmony import */ var _primeng_preset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./primeng-preset */ 80036); function provideUI() { return (0,primeng_config__WEBPACK_IMPORTED_MODULE_0__.providePrimeNG)({ theme: { options: { cssLayer: { name: 'primeng', order: 'theme, base, primeng, utilities' }, darkModeSelector: '.dark' }, preset: _primeng_preset__WEBPACK_IMPORTED_MODULE_1__.ThemePreset } }); } /***/ }, /***/ 20168 /*!*******************************************!*\ !*** ./libs/ui/src/lib/theme/semantic.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ semantic: () => (/* binding */ semantic) /* harmony export */ }); /* harmony import */ var _primeuix_themes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @primeuix/themes */ 28584); /** * Scheme-dependent semantic tokens. * * Every color that depends on the active scheme MUST live under * `colorScheme.dark` / `colorScheme.light` — anything at the semantic root is * scheme-invariant by definition and would leak into the other scheme. * * The `light` block mirrors the exact key set of `dark` so a missing token is * visible in a diff rather than discovered at runtime. Its values currently * repeat the `dark` values as placeholders (dark-on-dark in light mode) until * a light scheme is designed. */ const listOptionSelection = { option: { selectedBackground: '{surface.800}', selectedColor: '{text.color}', selectedFocusBackground: '{surface.700}', selectedFocusColor: '{text.color}' } }; const semantic = { colorScheme: { dark: { list: listOptionSelection, surface: (0,_primeuix_themes__WEBPACK_IMPORTED_MODULE_0__.palette)('{zinc}') }, light: { list: listOptionSelection, surface: (0,_primeuix_themes__WEBPACK_IMPORTED_MODULE_0__.palette)('{zinc}') } }, primary: (0,_primeuix_themes__WEBPACK_IMPORTED_MODULE_0__.palette)('{amber}') }; /***/ }, /***/ 7738 /*!**********************************************************************!*\ !*** ./libs/ui/src/lib/toolbar/tool-button/tool-button.component.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ToolButtonComponent: () => (/* binding */ ToolButtonComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 14975); class ToolButtonComponent { toolType = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "toolType" }] : [])); selectedToolType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "selectedToolType" }] : [])); active = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => this.toolType() === this.selectedToolType(), ...(ngDevMode ? [{ debugName: "active" }] : [])); selected = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); onClick(event_) { event_.preventDefault(); if (!this.active()) { this.selected.emit(); } } cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_3__.cn; static ɵfac = function ToolButtonComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ToolButtonComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵdefineComponent"]({ type: ToolButtonComponent, selectors: [["lib-tool-button"]], inputs: { toolType: [1, "toolType"], selectedToolType: [1, "selectedToolType"] }, outputs: { selected: "selected" }, decls: 3, vars: 5, consts: [[1, "flex", "items-center"], ["variant", "text", 3, "click", "styleClass", "aria-label"], [1, "size-(--p-app-icon-size-md)", 3, "icon"]], template: function ToolButtonComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementStart"](0, "span", 0)(1, "p-button", 1); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵlistener"]("click", function ToolButtonComponent_Template_p_button_click_1_listener($event) { return ctx.onClick($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelement"](2, "lib-icon", 2); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵariaProperty"]("aria-label", _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵinterpolate"](ctx.toolType())); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("styleClass", ctx.cn(ctx.active() ? "active text-primary-400" : "text-surface-100", "flex items-center justify-center rounded-none p-2 hover:bg-surface-700 transition-all duration-150 ease-in-out")); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵattribute"]("data-test-id", `tool-button-p-button-${ctx.toolType()}`); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_5__["ɵɵproperty"]("icon", ctx.toolType()); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__.IconComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 97850 /*!******************************************************!*\ !*** ./libs/ui/src/lib/toolbar/toolbar.component.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ToolbarComponent: () => (/* binding */ ToolbarComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_motion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/motion */ 62367); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _tool_button_tool_button_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./tool-button/tool-button.component */ 7738); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 14975); function ToolbarComponent_For_3_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "lib-tool-button", 8); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("selected", function ToolbarComponent_For_3_Template_lib_tool_button_selected_0_listener() { const toolType_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r1).$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.toolButtonClicked(toolType_r2)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const toolType_r2 = ctx.$implicit; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("toolType", toolType_r2)("selectedToolType", ctx_r2.activeTool()); } } function ToolbarComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "span", 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const progress_r5 = ctx; _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate2"](" ", progress_r5.current, " / ", progress_r5.total, " "); } } function ToolbarComponent_Conditional_8_Case_12_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r7 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-button", 20); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Conditional_8_Case_12_Conditional_0_Conditional_0_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r7); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](4); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.undo()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("rounded", true)("text", true); } } function ToolbarComponent_Conditional_8_Case_12_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](0, ToolbarComponent_Conditional_8_Case_12_Conditional_0_Conditional_0_Template, 1, 2, "p-button", 19); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"](ctx.current > 1 ? 0 : -1); } } function ToolbarComponent_Conditional_8_Case_12_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](0, ToolbarComponent_Conditional_8_Case_12_Conditional_0_Template, 1, 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](1, "p-button", 18); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Conditional_8_Case_12_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r6); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.startFillingPlaceholder()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { let tmp_3_0; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_3_0 = ctx_r2.protocolProgress()) ? 0 : -1, tmp_3_0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("rounded", true)("text", true); } } function ToolbarComponent_Conditional_8_Case_13_Template(rf, ctx) { if (rf & 1) { const _r8 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-button", 21); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Conditional_8_Case_13_Template_p_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r8); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.restartStep()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](1, "p-button", 22); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Conditional_8_Case_13_Template_p_button_click_1_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r8); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.endPlaceholder()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("rounded", true)("text", true); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("rounded", true)("text", true); } } function ToolbarComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 7)(1, "div", 9)(2, "span", 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](4, ToolbarComponent_Conditional_8_Conditional_4_Template, 2, 2, "span", 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](5, "div", 11)(6, "span", 12)(7, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](8, "lib-icon", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](9, "span", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](11, "div", 16); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](12, ToolbarComponent_Conditional_8_Case_12_Template, 2, 3)(13, ToolbarComponent_Conditional_8_Case_13_Template, 2, 4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](14, "p-button", 17); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Conditional_8_Template_p_button_click_14_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵresetView"](ctx_r2.cancelProtocol()); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()()(); } if (rf & 2) { let tmp_3_0; let tmp_7_0; const placeholder_r9 = ctx; const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate1"](" ", ctx_r2.stageLabel(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_3_0 = ctx_r2.protocolProgress()) ? 4 : -1, tmp_3_0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵstyleProp"]("color", placeholder_r9.color); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("icon", placeholder_r9.annotationType); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate1"](" ", placeholder_r9.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_7_0 = ctx_r2.stage()) === "preparation" ? 12 : tmp_7_0 === "confirmation" ? 13 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("rounded", true)("text", true); } } const STAGE_LABELS = { confirmation: 'Confirm', creation: 'Create', inactive: '', preparation: 'Find' }; class ToolbarComponent { toolTypes = [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.POINT, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.DISTANCE, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.ANGLE, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.OPEN_SPLINE, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_4__.AnnotationSourceType.CLOSED_SPLINE]; activeTool = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "activeTool" }] : [])); activePlaceholder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "activePlaceholder" }] : [])); activePlaceholderFilled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "activePlaceholderFilled" }] : [])); protocolProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(undefined, ...(ngDevMode ? [{ debugName: "protocolProgress" }] : [])); toolChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); openRelativeMeasurements = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); createObject3DClicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); startPlaceholder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); placeholderComplete = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); protocolCancelled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); stepRestarted = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); undoPlaceholder = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); stage = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const tool = this.activeTool(); const placeholder = this.activePlaceholder(); const placeholderFilled = this.activePlaceholderFilled(); if (placeholderFilled) { return 'confirmation'; } if (placeholder && tool) { return 'creation'; } if (placeholder) { return 'preparation'; } return 'inactive'; }, ...(ngDevMode ? [{ debugName: "stage" }] : [])); stageLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const stage = this.stage(); return STAGE_LABELS[stage]; }, ...(ngDevMode ? [{ debugName: "stageLabel" }] : [])); toolButtonClicked(toolType) { this.toolChanged.emit(toolType); } openRelativeMeasurementsMenu(event_) { event_.preventDefault(); this.openRelativeMeasurements.emit(event_); } createObject3D(event_) { event_.preventDefault(); this.createObject3DClicked.emit(event_); } startFillingPlaceholder() { const tool = this.activeTool(); const placeholder = this.activePlaceholder(); if (placeholder && !tool) { this.startPlaceholder.emit(placeholder); } } endPlaceholder() { const placeholder = this.activePlaceholder(); if (placeholder) { this.placeholderComplete.emit(placeholder); } } cancelProtocol() { this.protocolCancelled.emit(); } restartStep() { this.stepRestarted.emit(); } undo() { this.undoPlaceholder.emit(); } static ɵfac = function ToolbarComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ToolbarComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵdefineComponent"]({ type: ToolbarComponent, selectors: [["lib-toolbar"]], inputs: { activeTool: [1, "activeTool"], activePlaceholder: [1, "activePlaceholder"], activePlaceholderFilled: [1, "activePlaceholderFilled"], protocolProgress: [1, "protocolProgress"] }, outputs: { toolChanged: "toolChanged", openRelativeMeasurements: "openRelativeMeasurements", createObject3DClicked: "createObject3DClicked", startPlaceholder: "startPlaceholder", placeholderComplete: "placeholderComplete", protocolCancelled: "protocolCancelled", stepRestarted: "stepRestarted", undoPlaceholder: "undoPlaceholder" }, decls: 9, vars: 9, consts: [[1, "bg-surface-800", "relative", "z-10", "flex", "flex-col", "overflow-hidden", "rounded-md", "p-0", "shadow-lg/25"], [1, "inline-flex", "w-[294px]"], [3, "toolType", "selectedToolType"], ["data-test-id", "toolbar-p-button-measurements", "pMotionType", "transition", "variant", "text", 3, "click", "disabled", "pMotionDuration", "pMotion", "styleClass"], ["icon", "relative-measurements", "iconClass", "text-surface-100", 1, "size-(--p-app-icon-size-md)"], ["data-test-id", "toolbar-p-button-create-object3d", "pMotionType", "transition", "variant", "text", 3, "click", "disabled", "pMotionDuration", "pMotion", "styleClass"], ["icon", "object-3d", "iconClass", "text-surface-100", 1, "size-(--p-app-icon-size-md)"], [1, "bg-surface-900", "relative", "z-0", "-mt-2", "flex", "w-[294px]", "flex-col", "rounded-b-md", "shadow-lg/25"], [3, "selected", "toolType", "selectedToolType"], [1, "mt-2", "flex", "items-center", "justify-between", "overflow-clip"], [1, "text-color", "mx-2", "mt-1", "text-xs"], [1, "flex", "items-center", "justify-between", "overflow-clip"], [1, "flex", "items-center"], [1, "bg-surface-900", "mx-2", "my-1", "flex", "size-7.5", "shrink-0", "items-center", "justify-center", "rounded-full"], [1, "size-(--p-app-icon-size-sm)", 3, "icon"], [1, "text-color", "text-wrap", "break-all"], [1, "flex", "items-center", "justify-end", "overflow-clip"], ["data-test-id", "toolbar-p-button-cancel-protocol", "icon", "pi pi-times", "size", "small", "severity", "danger", 3, "click", "rounded", "text"], ["data-test-id", "toolbar-p-button-start-placeholder", "icon", "pi pi-play", "size", "small", "severity", "success", 3, "click", "rounded", "text"], ["data-test-id", "toolbar-p-button-undo-placeholder", "icon", "pi pi-undo", "size", "small", "severity", "primary", 3, "rounded", "text"], ["data-test-id", "toolbar-p-button-undo-placeholder", "icon", "pi pi-undo", "size", "small", "severity", "primary", 3, "click", "rounded", "text"], ["data-test-id", "toolbar-p-button-restart-placeholder", "icon", "pi pi-undo", "size", "small", "severity", "primary", 3, "click", "rounded", "text"], ["data-test-id", "toolbar-p-button-confirm-placeholder", "icon", "pi pi-check", "size", "small", "severity", "success", 3, "click", "rounded", "text"]], template: function ToolbarComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 0)(1, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](2, ToolbarComponent_For_3_Template, 1, 2, "lib-tool-button", 2, _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterTrackByIdentity"]); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](4, "p-button", 3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Template_p_button_click_4_listener($event) { return ctx.openRelativeMeasurementsMenu($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](5, "lib-icon", 4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](6, "p-button", 5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("click", function ToolbarComponent_Template_p_button_click_6_listener($event) { return ctx.createObject3D($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](7, "lib-icon", 6); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](8, ToolbarComponent_Conditional_8_Template, 15, 9, "div", 7); } if (rf & 2) { let tmp_9_0; _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx.toolTypes); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("disabled", ctx.activeTool() !== undefined)("pMotionDuration", 150)("pMotion", true)("styleClass", "rel-measurements-btn rounded-none flex items-center justify-center p-2 bg-surface-600"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("disabled", ctx.activeTool() !== undefined)("pMotionDuration", 150)("pMotion", true)("styleClass", "create-object3d-btn rounded-none flex items-center justify-center p-2 bg-surface-600"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_9_0 = ctx.activePlaceholder()) ? 8 : -1, tmp_9_0); } }, dependencies: [_tool_button_tool_button_component__WEBPACK_IMPORTED_MODULE_6__.ToolButtonComponent, primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, _icon_icon_component__WEBPACK_IMPORTED_MODULE_5__.IconComponent, primeng_motion__WEBPACK_IMPORTED_MODULE_3__.MotionDirective], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 14486 /*!**********************************************************************!*\ !*** ./libs/ui/src/lib/viewport-button/viewport-button.component.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportButtonComponent: () => (/* binding */ ViewportButtonComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["internalButton"]; const _c1 = ["*"]; class ViewportButtonComponent { buttonInstance = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.viewChild)('internalButton', ...(ngDevMode ? [{ debugName: "buttonInstance" }] : [])); icon = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "icon" }] : [])); iconType = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('auto', ...(ngDevMode ? [{ debugName: "iconType" }] : [])); tooltip = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "tooltip" }] : [])); ariaLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : [])); disabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "disabled" }] : [])); iconClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('size-4', ...(ngDevMode ? [{ debugName: "iconClass" }] : [])); tooltipPosition = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('top', ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : [])); tooltipStyleClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "tooltipStyleClass" }] : [])); pt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)({}, ...(ngDevMode ? [{ debugName: "pt" }] : [])); combinedPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { return { ...this.pt(), root: (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.cn)(`size-7 flex items-center justify-center text-(--p-app-viewport-label) hover:bg-(--p-app-viewport-label)/35 text-shadow-[0_0_3px_var(--p-app-viewport-outline),0_0_3px_var(--p-app-viewport-outline)]`, this.pt()?.root) }; }, ...(ngDevMode ? [{ debugName: "combinedPt" }] : [])); focus() { this.buttonInstance()?.el.nativeElement.querySelector('button')?.focus(); } static ɵfac = function ViewportButtonComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportButtonComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: ViewportButtonComponent, selectors: [["lib-viewport-button"]], viewQuery: function ViewportButtonComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵviewQuerySignal"](ctx.buttonInstance, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵqueryAdvance"](); } }, inputs: { icon: [1, "icon"], iconType: [1, "iconType"], tooltip: [1, "tooltip"], ariaLabel: [1, "ariaLabel"], disabled: [1, "disabled"], iconClass: [1, "iconClass"], tooltipPosition: [1, "tooltipPosition"], tooltipStyleClass: [1, "tooltipStyleClass"], pt: [1, "pt"] }, ngContentSelectors: _c1, decls: 5, vars: 10, consts: [["internalButton", ""], [1, "inline-flex", 3, "pTooltip", "tooltipPosition", "tooltipStyleClass"], ["rounded", "", "text", "", "size", "small", 3, "ariaLabel", "disabled", "pt"], [1, "size-(--p-app-icon-size-xs)", 3, "icon", "iconClass", "iconType"]], template: function ViewportButtonComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojectionDef"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "span", 1)(1, "p-button", 2, 0); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](3, "lib-icon", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵprojection"](4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", ctx.tooltip())("tooltipPosition", ctx.tooltipPosition())("tooltipStyleClass", ctx.tooltipStyleClass()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("ariaLabel", ctx.ariaLabel())("disabled", ctx.disabled())("pt", ctx.combinedPt()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵattribute"]("data-test-id", "viewport-button-p-button-" + ctx.icon()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("icon", ctx.icon())("iconClass", ctx.iconClass())("iconType", ctx.iconType()); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.TooltipModule, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, _icon_icon_component__WEBPACK_IMPORTED_MODULE_5__.IconComponent], encapsulation: 2 }); } /***/ }, /***/ 89416 /*!****************************************************************************!*\ !*** ./libs/ui/src/lib/viewport-indicator/viewport-indicator.component.ts ***! \****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportIndicatorComponent: () => (/* binding */ ViewportIndicatorComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 14975); class ViewportIndicatorComponent { viewportName = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "viewportName" }] : [])); focusedViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "focusedViewport" }] : [])); initialState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(true, ...(ngDevMode ? [{ debugName: "initialState" }] : [])); lastFocused = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "lastFocused" }] : [])); get ariaLabel() { return `Viewport name ${this.viewportName()}`; } viewportNameClass = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const viewportName = this.viewportName(); const focusedName = this.focusedViewport(); const blue = 'bg-(--p-app-viewport-indicator-coronal)'; const red = 'bg-(--p-app-viewport-indicator-sagittal)'; const green = 'bg-(--p-app-viewport-indicator-axial)'; let axialColor = green; let sagittalColor = red; let coronalColor = blue; switch (focusedName) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.AXIAL: { if (this.lastFocused() == _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.SAGITTAL) { coronalColor = green; axialColor = red; sagittalColor = blue; } else { axialColor = blue; coronalColor = green; } break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.CORONAL: { break; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.SAGITTAL: { if (this.lastFocused() == _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.AXIAL) { coronalColor = red; axialColor = blue; sagittalColor = green; } else { coronalColor = red; sagittalColor = blue; } break; } } if (viewportName == _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.AXIAL) { return axialColor; } else if (viewportName == _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.CORONAL) { return coronalColor; } else if (viewportName == _tomoverse_enums__WEBPACK_IMPORTED_MODULE_2__.ViewportName.SAGITTAL) { return sagittalColor; } else { return ''; } }, ...(ngDevMode ? [{ debugName: "viewportNameClass" }] : [])); static ɵfac = function ViewportIndicatorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportIndicatorComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineComponent"]({ type: ViewportIndicatorComponent, selectors: [["lib-viewport-indicator"]], inputs: { viewportName: [1, "viewportName"], focusedViewport: [1, "focusedViewport"], initialState: [1, "initialState"], lastFocused: [1, "lastFocused"] }, decls: 1, vars: 2, consts: [[3, "className"]], template: function ViewportIndicatorComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomElement"](0, "div", 0); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdomProperty"]("className", "size-4 absolute top-0 left-0 z-10 " + ctx.viewportNameClass()); _angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵattribute"]("aria-label", ctx.ariaLabel); } }, encapsulation: 2 }); } /***/ }, /***/ 55610 /*!**************************************************************************************!*\ !*** ./libs/ui/src/lib/viewport-layout-manager/viewport-layout-manager.component.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportLayoutManagerComponent: () => (/* binding */ ViewportLayoutManagerComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var primeng_splitter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! primeng/splitter */ 592); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _viewport_indicator_viewport_indicator_component__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../viewport-indicator/viewport-indicator.component */ 89416); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var primeng_api__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! primeng/api */ 62751); const _c0 = ["viewportAxial"]; const _c1 = ["viewportSagittal"]; const _c2 = ["viewportCoronal"]; const _c3 = ["viewportReformat"]; const _c4 = ["sCurveGraph"]; const _c5 = ["cprWorkspace"]; const _c6 = ["splitter"]; const _c7 = () => ({ height: "100%", width: "100%" }); const _c8 = () => [33, 33, 34]; const _c9 = () => [5, 5, 5]; const _c10 = (a0, a1) => ({ "animate-viewport-blur-in": a0, "animate-viewport-blur-out": a1 }); const _c11 = () => [5, 5]; const _forTrack0 = ($index, $item) => $item.name; function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_ng_template_0_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_ng_template_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_ng_template_0_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const viewport_r4 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", viewport_r4.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](7, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", viewport_r4.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", viewport_r4.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](0, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_ng_template_0_Template, 4, 10, "ng-template", 10); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_ng_template_0_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_ng_template_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_ng_template_0_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()(); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", "sCurveGraph"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](3, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx_r1.sCurveGraphTemplateRef()); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](0, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_ng_template_0_Template, 3, 6, "ng-template", 10); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Template(rf, ctx) { if (rf & 1) { const _r3 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-splitter", 11); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("onResizeStart", function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Template_p_splitter_onResizeStart_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeStart.emit($event)); })("onResizeEnd", function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Template_p_splitter_onResizeEnd_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r3); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeEnd.emit($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](1, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_For_2_Template, 1, 0, null, 10, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](3, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Conditional_3_Template, 1, 0, null, 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("minSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](2, _c9)); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx_r1.layout().leftPanelViewports); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"](ctx_r1.showSCurveGraph() ? 3 : -1); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_3_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_3_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", ctx_r1.layout().middlePanelViewport.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](7, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx_r1.layout().middlePanelViewport.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", ctx_r1.layout().middlePanelViewport.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_4_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_4_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 16); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", ctx_r1.layout().middlePanelViewport.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](4, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx_r1.reformatTemplateRef()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", ctx_r1.ViewportName.REFORMAT); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-splitter", 9, 0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("onResizeStart", function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_Template_p_splitter_onResizeStart_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeStart.emit($event)); })("onResizeEnd", function ViewportLayoutManagerComponent_Conditional_1_Conditional_0_Template_p_splitter_onResizeEnd_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeEnd.emit($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_2_Template, 4, 3, "ng-template", 10)(3, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_3_Template, 4, 10, "ng-template", 10)(4, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_ng_template_4_Template, 4, 7, "ng-template", 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵstyleMap"](_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](4, _c7)); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("panelSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](5, _c8))("minSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](6, _c9)); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_ng_template_0_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_ng_template_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_ng_template_0_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const viewport_r7 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"]().$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", viewport_r7.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](7, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", viewport_r7.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", viewport_r7.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](0, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_ng_template_0_Template, 4, 10, "ng-template", 10); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_Template(rf, ctx) { if (rf & 1) { const _r6 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-splitter", 11); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("onResizeStart", function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_Template_p_splitter_onResizeStart_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeStart.emit($event)); })("onResizeEnd", function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_Template_p_splitter_onResizeEnd_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r6); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeEnd.emit($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](1, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_For_2_Template, 1, 0, null, 10, _forTrack0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("minSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](1, _c11)); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx_r1.layout().leftPanelViewports); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_3_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_3_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", ctx_r1.layout().middlePanelViewport.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](7, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx_r1.layout().middlePanelViewport.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", ctx_r1.layout().middlePanelViewport.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_4_ng_container_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_4_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 12)(1, "div", 13); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_4_ng_container_2_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](3, "lib-viewport-indicator", 16); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵattribute"]("data-viewport", ctx_r1.layout().middlePanelViewport.name); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngClass", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction2"](4, _c10, ctx_r1.isBlur(), !ctx_r1.isBlur())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx_r1.reformatTemplateRef()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", ctx_r1.ViewportName.REFORMAT); } } function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r5 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "p-splitter", 9, 0); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("onResizeStart", function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_Template_p_splitter_onResizeStart_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r5); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeStart.emit($event)); })("onResizeEnd", function ViewportLayoutManagerComponent_Conditional_1_Conditional_1_Template_p_splitter_onResizeEnd_0_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r5); const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r1.resizeEnd.emit($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](2, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_2_Template, 3, 2, "ng-template", 10)(3, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_3_Template, 4, 10, "ng-template", 10)(4, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_ng_template_4_Template, 4, 7, "ng-template", 10); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵstyleMap"](_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](4, _c7)); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("panelSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](5, _c8))("minSizes", _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpureFunction0"](6, _c9)); } } function ViewportLayoutManagerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](0, ViewportLayoutManagerComponent_Conditional_1_Conditional_0_Template, 5, 7, "p-splitter", 8)(1, ViewportLayoutManagerComponent_Conditional_1_Conditional_1_Template, 5, 7, "p-splitter", 8); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"](ctx_r1.showSCurveGraph() ? 0 : 1); } } function ViewportLayoutManagerComponent_Conditional_2_Conditional_0_ng_container_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](1, ViewportLayoutManagerComponent_Conditional_2_Conditional_0_ng_container_1_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", ctx); } } function ViewportLayoutManagerComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](0, ViewportLayoutManagerComponent_Conditional_2_Conditional_0_Template, 2, 1, "div", 1); } if (rf & 2) { let tmp_1_0; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_1_0 = ctx_r1.cprWorkspaceTemplateRef()) ? 0 : -1, tmp_1_0); } } function ViewportLayoutManagerComponent_Conditional_3_Conditional_0_ng_container_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_3_Conditional_0_For_5_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementContainer"](0); } } function ViewportLayoutManagerComponent_Conditional_3_Conditional_0_For_5_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](0, ViewportLayoutManagerComponent_Conditional_3_Conditional_0_For_5_ng_container_0_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](1, "lib-viewport-indicator", 15); } if (rf & 2) { const viewport_r8 = ctx.$implicit; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", viewport_r8.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", viewport_r8.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); } } function ViewportLayoutManagerComponent_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 17); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtemplate"](1, ViewportLayoutManagerComponent_Conditional_3_Conditional_0_ng_container_1_Template, 1, 0, "ng-container", 14); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](2, "lib-viewport-indicator", 15); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](3, "div", 18); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterCreate"](4, ViewportLayoutManagerComponent_Conditional_3_Conditional_0_For_5_Template, 2, 5, null, null, _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeaterTrackByIndex"]); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()(); } if (rf & 2) { const focused_r9 = ctx; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("ngTemplateOutlet", focused_r9.templateRef); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵproperty"]("viewportName", focused_r9.name)("focusedViewport", ctx_r1.selectedMPRViewport())("initialState", ctx_r1.isInitialViewportState())("lastFocused", ctx_r1.lastSelectedMPRViewport()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵrepeater"](ctx_r1.layout().hiddenViewports); } } function ViewportLayoutManagerComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](0, ViewportLayoutManagerComponent_Conditional_3_Conditional_0_Template, 6, 5, "div", 17); } if (rf & 2) { let tmp_1_0; const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"]((tmp_1_0 = ctx_r1.layout().maximizedViewport) ? 0 : -1, tmp_1_0); } } function ViewportLayoutManagerComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r1 = _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate"](ctx_r1.loaderInstanceCount()); } } class ViewportLayoutManagerComponent { ViewportName = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName; panelLatch = true; viewportLayout = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "viewportLayout" }] : [])); focusedMPRViewport = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "focusedMPRViewport" }] : [])); selectedMPRViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "selectedMPRViewport" }] : [])); lastSelectedMPRViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.CORONAL, ...(ngDevMode ? [{ debugName: "lastSelectedMPRViewport" }] : [])); showSCurveGraph = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "showSCurveGraph" }] : [])); isBlur = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "isBlur" }] : [])); loadingProgress = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(...(ngDevMode ? [undefined, { debugName: "loadingProgress" }] : [])); isInitialViewportState = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, ...(ngDevMode ? [{ debugName: "isInitialViewportState" }] : [])); loaderContextMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); LayoutType = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType; resizeStart = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); resizeEnd = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); orientations = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName; axialTemplateRef = _angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild.required('viewportAxial'); sagittalTemplateRef = _angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild.required('viewportSagittal'); coronalTemplateRef = _angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild.required('viewportCoronal'); reformatTemplateRef = _angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild.required('viewportReformat'); sCurveGraphTemplateRef = _angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild.required('sCurveGraph'); // Optional: only consumers that render the CPR layout project a workspace. cprWorkspaceTemplateRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.contentChild)('cprWorkspace', ...(ngDevMode ? [{ debugName: "cprWorkspaceTemplateRef" }] : [])); splitter = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild)('splitter', ...(ngDevMode ? [{ debugName: "splitter" }] : [])); updater = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.effect)(() => { this.showSCurveGraph(); const splitter = this.splitter(); if (splitter) { splitter.panels = [...splitter.panels]; splitter.cd.detectChanges(); } }, ...(ngDevMode ? [{ debugName: "updater" }] : [])); allViewports = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => ({ [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.AXIAL]: this.axialTemplateRef(), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.CORONAL]: this.coronalTemplateRef(), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.REFORMAT]: this.reformatTemplateRef(), [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.SAGITTAL]: this.sagittalTemplateRef() }), ...(ngDevMode ? [{ debugName: "allViewports" }] : [])); layout = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const focused = this.focusedMPRViewport(); const layoutType = this.viewportLayout(); return { hiddenViewports: this.getHiddenViewports(layoutType), leftPanelViewports: this.getLeftPanelViewports(focused), maximizedViewport: this.getMaximizedViewport(layoutType), middlePanelViewport: this.getMiddlePanelViewport(focused) }; }, ...(ngDevMode ? [{ debugName: "layout" }] : [])); showGlobalLoader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.loadingProgress()?.loading ?? false, ...(ngDevMode ? [{ debugName: "showGlobalLoader" }] : [])); loaderPercent = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.loadingProgress()?.percent ?? 0, ...(ngDevMode ? [{ debugName: "loaderPercent" }] : [])); allInstancesFetched = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const progress = this.loadingProgress(); return progress !== undefined && progress.totalCount > 0 && progress.cachedCount >= progress.totalCount; }, ...(ngDevMode ? [{ debugName: "allInstancesFetched" }] : [])); loaderMessageKey = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => this.allInstancesFetched() ? 'viewportLoader.constructingVolume' : 'viewportLoader.fetchingInstances', ...(ngDevMode ? [{ debugName: "loaderMessageKey" }] : [])); loaderInstanceCount = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const progress = this.loadingProgress(); return progress === undefined ? '' : `${progress.cachedCount}/${progress.totalCount}`; }, ...(ngDevMode ? [{ debugName: "loaderInstanceCount" }] : [])); getViewportConfig(name) { return { name, templateRef: this.allViewports()[name] }; } getViewportConfigsExcluding(...excludeNames) { const allViewports = this.allViewports(); return Object.entries(allViewports).filter(([name]) => !excludeNames.includes(name)).map(([name, viewport]) => ({ name: name, templateRef: viewport })); } getLeftPanelViewports(excludeName) { return this.getViewportConfigsExcluding(excludeName, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.REFORMAT); } getMiddlePanelViewport(focusedViewportName) { return this.getViewportConfig(focusedViewportName); } getMaximizedViewport(layoutType) { switch (layoutType) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_3D: { return this.getViewportConfig(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.REFORMAT); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_AXIAL: { return this.getViewportConfig(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.AXIAL); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_CORONAL: { return this.getViewportConfig(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.CORONAL); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_S_CURVE: { return { name: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.PanelName.S_CURVE_GRAPH, templateRef: this.sCurveGraphTemplateRef() }; } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_SAGITTAL: { return this.getViewportConfig(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.SAGITTAL); } default: { return undefined; } } } getHiddenViewports(layoutType) { switch (layoutType) { case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_3D: { return this.getViewportConfigsExcluding(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.REFORMAT); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_AXIAL: { return this.getViewportConfigsExcluding(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.AXIAL); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_CORONAL: { return this.getViewportConfigsExcluding(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.CORONAL); } case _tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.LayoutType.MAXIMIZE_SAGITTAL: { return this.getViewportConfigsExcluding(_tomoverse_enums__WEBPACK_IMPORTED_MODULE_6__.ViewportName.SAGITTAL); } default: { return []; } } } static ɵfac = function ViewportLayoutManagerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportLayoutManagerComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵdefineComponent"]({ type: ViewportLayoutManagerComponent, selectors: [["lib-viewport-layout-manager"]], contentQueries: function ViewportLayoutManagerComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵcontentQuerySignal"](dirIndex, ctx.axialTemplateRef, _c0, 5)(dirIndex, ctx.sagittalTemplateRef, _c1, 5)(dirIndex, ctx.coronalTemplateRef, _c2, 5)(dirIndex, ctx.reformatTemplateRef, _c3, 5)(dirIndex, ctx.sCurveGraphTemplateRef, _c4, 5)(dirIndex, ctx.cprWorkspaceTemplateRef, _c5, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵqueryAdvance"](6); } }, viewQuery: function ViewportLayoutManagerComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵviewQuerySignal"](ctx.splitter, _c6, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵqueryAdvance"](); } }, inputs: { viewportLayout: [1, "viewportLayout"], focusedMPRViewport: [1, "focusedMPRViewport"], selectedMPRViewport: [1, "selectedMPRViewport"], lastSelectedMPRViewport: [1, "lastSelectedMPRViewport"], showSCurveGraph: [1, "showSCurveGraph"], isBlur: [1, "isBlur"], loadingProgress: [1, "loadingProgress"], isInitialViewportState: [1, "isInitialViewportState"] }, outputs: { loaderContextMenu: "loaderContextMenu", resizeStart: "resizeStart", resizeEnd: "resizeEnd" }, decls: 13, vars: 11, consts: [["splitter", ""], [1, "relative", "h-full", "w-full"], [1, "viewport-loader", "absolute", "inset-0", "z-10", "flex", "items-center", "justify-center", "bg-(--p-app-viewport-background)/100", "transition-opacity", "duration-300", 3, "contextmenu"], [1, "border-surface-700", "w-72", "max-w-[85vw]", "rounded-lg", "border", "bg-(--p-app-viewport-background)/90", "p-4"], [1, "mb-2", "flex", "justify-between", "gap-4", "text-sm", "font-medium", "text-(--p-app-viewport-label)"], [1, "text-right", "tabular-nums"], [1, "bg-surface-700", "h-2", "w-full", "overflow-hidden", "rounded-full"], [1, "bg-primary-300", "h-full", "transition-all", "duration-200"], [3, "style", "panelSizes", "minSizes"], [3, "onResizeStart", "onResizeEnd", "panelSizes", "minSizes"], ["pTemplate", ""], ["layout", "vertical", 3, "onResizeStart", "onResizeEnd", "minSizes"], [1, "relative", "h-full", "w-full", "bg-(--p-app-viewport-background)"], [1, "h-full", "w-full", 3, "ngClass"], [4, "ngTemplateOutlet"], [3, "viewportName", "focusedViewport", "initialState", "lastFocused"], [3, "viewportName"], [1, "animate-viewport-fade-in", "h-full", "w-full", "overflow-clip"], [1, "invisible", "size-100", "overflow-hidden"]], template: function ViewportLayoutManagerComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](0, "section", 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](1, ViewportLayoutManagerComponent_Conditional_1_Template, 2, 1)(2, ViewportLayoutManagerComponent_Conditional_2_Template, 1, 1)(3, ViewportLayoutManagerComponent_Conditional_3_Template, 1, 1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](4, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵlistener"]("contextmenu", function ViewportLayoutManagerComponent_Template_div_contextmenu_4_listener($event) { $event.preventDefault(); $event.stopPropagation(); return ctx.loaderContextMenu.emit($event); }); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](5, "div", 3)(6, "div", 4)(7, "div"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipe"](9, "translate"); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditionalCreate"](10, ViewportLayoutManagerComponent_Conditional_10_Template, 2, 1, "div", 5); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementStart"](11, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelement"](12, "div", 7); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵelementEnd"]()()()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"](ctx.panelLatch && ctx.viewportLayout() === ctx.LayoutType.DEFAULT ? 1 : ctx.viewportLayout() === ctx.LayoutType.CPR ? 2 : 3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵclassProp"]("opacity-0", !ctx.showGlobalLoader())("pointer-events-none", !ctx.showGlobalLoader()); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](4); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵtextInterpolate"](_angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵpipeBind1"](9, 9, ctx.loaderMessageKey())); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵconditional"](!ctx.allInstancesFetched() ? 10 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_8__["ɵɵstyleProp"]("width", ctx.loaderPercent(), "%"); } }, dependencies: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgClass, _angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet, primeng_splitter__WEBPACK_IMPORTED_MODULE_5__.SplitterModule, primeng_splitter__WEBPACK_IMPORTED_MODULE_5__.Splitter, primeng_api__WEBPACK_IMPORTED_MODULE_9__.PrimeTemplate, _viewport_indicator_viewport_indicator_component__WEBPACK_IMPORTED_MODULE_7__.ViewportIndicatorComponent, _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslatePipe], encapsulation: 2 }); } /***/ }, /***/ 346 /*!**************************************************************************************!*\ !*** ./libs/ui/src/lib/viewport-setting-slider/viewport-setting-slider.component.ts ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ViewportSettingSliderComponent: () => (/* binding */ ViewportSettingSliderComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var primeng_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/button */ 94481); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _slider_slider_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../slider/slider.component */ 80922); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ root: "size-7.5 p-0" }); function ViewportSettingSliderComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "span", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵattribute"]("data-test-id", `viewport-setting-slider-span-value-${ctx_r0.label().toLowerCase()}`); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx_r0.displayText(), " "); } } class ViewportSettingSliderComponent { label = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "label" }] : [])); minValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "minValue" }] : [])); maxValue = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "maxValue" }] : [])); value = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.model)(...(ngDevMode ? [undefined, { debugName: "value" }] : [])); step = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "step" }] : [])); isDisabled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : [])); tooltip = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "tooltip" }] : [])); showValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(false, { ...(ngDevMode ? { debugName: "showValue" } : {}), transform: _angular_core__WEBPACK_IMPORTED_MODULE_0__.booleanAttribute }); valueSuffix = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)('', ...(ngDevMode ? [{ debugName: "valueSuffix" }] : [])); valueFormatter = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "valueFormatter" }] : [])); displayValue = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const value = this.value(); if (value === undefined) return ''; const decimals = (String(this.step() ?? 1).split('.')[1] ?? '').length; return value.toFixed(decimals); }, ...(ngDevMode ? [{ debugName: "displayValue" }] : [])); displayText = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.computed)(() => { const value = this.value(); if (value === undefined) return ''; const formatter = this.valueFormatter(); if (formatter) return formatter(value); return this.displayValue() + this.valueSuffix(); }, ...(ngDevMode ? [{ debugName: "displayText" }] : [])); sliderValueChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); slideEnd = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); resetClicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); dragStart = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); dragEnd = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.output)(); isDragging = false; onSliderMouseUp() { if (this.isDragging) { this.isDragging = false; this.dragEnd.emit(); } } onSliderMouseDown() { this.isDragging = true; this.dragStart.emit(); } handleKeyDown(event) { const min = this.minValue() ?? 0; const max = this.maxValue() ?? 0; const step = this.step() ?? 1; const stepFactor = step; const currentValue = this.value() ?? 0; if (event.key === 'ArrowRight' || event.key === 'ArrowUp') { event.preventDefault(); const newValue = Math.min(max, currentValue + stepFactor); this.onValueChange(newValue); } if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') { event.preventDefault(); const newValue = Math.max(min, currentValue - stepFactor); this.onValueChange(newValue); } } onValueChange(value) { if (value === undefined || value === null) return; this.value.set(value); this.sliderValueChanged.emit(Number(value)); } /** * PrimeNG only commits values on throttled `mousemove`, never on release, * so a fast drag stops short of the track end. */ onSlideEnd(value) { this.value.set(value); this.sliderValueChanged.emit(Number(value)); this.slideEnd.emit(value); } onReset() { this.resetClicked.emit(); } static ɵfac = function ViewportSettingSliderComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewportSettingSliderComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: ViewportSettingSliderComponent, selectors: [["lib-viewport-setting-slider"]], inputs: { label: [1, "label"], minValue: [1, "minValue"], maxValue: [1, "maxValue"], value: [1, "value"], step: [1, "step"], isDisabled: [1, "isDisabled"], tooltip: [1, "tooltip"], showValue: [1, "showValue"], valueSuffix: [1, "valueSuffix"], valueFormatter: [1, "valueFormatter"] }, outputs: { value: "valueChange", sliderValueChanged: "sliderValueChanged", slideEnd: "slideEnd", resetClicked: "resetClicked", dragStart: "dragStart", dragEnd: "dragEnd" }, decls: 7, vars: 16, consts: [[1, "grid", "w-80", "items-center", "gap-4"], ["tooltipPosition", "left", 1, "truncate", "text-right", "text-xs", 3, "pTooltip"], [3, "sliderChanged", "slideEnd", "keyDown", "mouseDown", "mouseUp", "dataTestIdOverride", "sliderMin", "sliderMax", "sliderStep", "sliderValue", "isDisabled", "sliderClassName"], ["pTooltip", "Reset to default", "text", "", "size", "small", "severity", "secondary", 3, "onClick", "pt", "disabled"], ["icon", "refresh"], [1, "min-w-15", "text-left", "text-xs", "whitespace-nowrap", "tabular-nums"]], template: function ViewportSettingSliderComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 0)(1, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](3, "lib-slider", 2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("sliderChanged", function ViewportSettingSliderComponent_Template_lib_slider_sliderChanged_3_listener($event) { return ctx.onValueChange($event); })("slideEnd", function ViewportSettingSliderComponent_Template_lib_slider_slideEnd_3_listener($event) { return ctx.onSlideEnd($event); })("keyDown", function ViewportSettingSliderComponent_Template_lib_slider_keyDown_3_listener($event) { return ctx.handleKeyDown($event); })("mouseDown", function ViewportSettingSliderComponent_Template_lib_slider_mouseDown_3_listener() { return ctx.onSliderMouseDown(); })("mouseUp", function ViewportSettingSliderComponent_Template_lib_slider_mouseUp_3_listener() { return ctx.onSliderMouseUp(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](4, "p-button", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵlistener"]("onClick", function ViewportSettingSliderComponent_Template_p_button_onClick_4_listener() { return ctx.onReset(); }); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](5, "lib-icon", 4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditionalCreate"](6, ViewportSettingSliderComponent_Conditional_6_Template, 2, 2, "span", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵclassMap"](ctx.showValue() ? "grid-cols-[90px_1fr_auto_auto]" : "grid-cols-[90px_1fr_auto]"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", ctx.tooltip() ?? ctx.label()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx.label(), " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("dataTestIdOverride", `viewport-setting-slider-slider-${ctx.label().toLowerCase()}`)("sliderMin", ctx.minValue())("sliderMax", ctx.maxValue())("sliderStep", ctx.step() ?? 1)("sliderValue", ctx.value() ?? ctx.minValue())("isDisabled", !!ctx.isDisabled())("sliderClassName", "min-w-0 w-full pointer-events-auto"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pt", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](15, _c0))("disabled", ctx.isDisabled()); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵattribute"]("data-test-id", `viewport-setting-slider-p-button-reset-${ctx.label().toLowerCase()}`); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵconditional"](ctx.showValue() ? 6 : -1); } }, dependencies: [primeng_button__WEBPACK_IMPORTED_MODULE_2__.ButtonModule, primeng_button__WEBPACK_IMPORTED_MODULE_2__.Button, _slider_slider_component__WEBPACK_IMPORTED_MODULE_5__.SliderComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, _icon_icon_component__WEBPACK_IMPORTED_MODULE_4__.IconComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 76042 /*!**********************************************************************!*\ !*** ./libs/ui/src/lib/volume-viewport/volume-viewport.component.ts ***! \**********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VolumeViewportComponent: () => (/* binding */ VolumeViewportComponent) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @ngx-translate/core */ 96110); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../viewport-button/viewport-button.component */ 14486); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = ["container"]; const _c1 = ["*"]; const _c2 = a0 => ["size-full", a0]; const _c3 = a0 => ({ state: a0 }); const _c4 = (a0, a1) => ({ ...a0, isDarkMode: a1 }); function VolumeViewportComponent_Conditional_1_ng_container_1_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementContainer"](0); } } function VolumeViewportComponent_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r2.angleLabel().isPosterior ? "(P)" : "", " "); } } function VolumeViewportComponent_Conditional_1_Conditional_14_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementContainer"](0); } } function VolumeViewportComponent_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](0, VolumeViewportComponent_Conditional_1_Conditional_14_ng_container_0_Template, 1, 0, "ng-container", 14); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("ngTemplateOutlet", ctx_r2.settingsPopoverTemplate())("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵpureFunction1"](2, _c3, ctx_r2.state())); } } function VolumeViewportComponent_Conditional_1_Conditional_15_Template(rf, ctx) { if (rf & 1) { const _r4 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "lib-viewport-button", 15); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("click", function VolumeViewportComponent_Conditional_1_Conditional_15_Template_lib_viewport_button_click_0_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r4); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](2); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.onFocusedMPRViewportChange()); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("tooltip", ctx_r2.swapLabel())("ariaLabel", ctx_r2.swapLabel()); } } function VolumeViewportComponent_Conditional_1_Conditional_16_ng_container_0_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementContainer"](0); } } function VolumeViewportComponent_Conditional_1_Conditional_16_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](0, VolumeViewportComponent_Conditional_1_Conditional_16_ng_container_0_Template, 1, 0, "ng-container", 14); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("ngTemplateOutlet", ctx_r2.viewportSettingsPopoverTemplate())("ngTemplateOutletContext", _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵpureFunction1"](5, _c3, _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵpureFunction2"](2, _c4, ctx_r2.state(), ctx_r2.darkMode()))); } } function VolumeViewportComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) { const _r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtemplate"](1, VolumeViewportComponent_Conditional_1_ng_container_1_Template, 1, 0, "ng-container", 4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](2, "div", 5)(3, "div", 6); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("contextmenu", function VolumeViewportComponent_Conditional_1_Template_div_contextmenu_3_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.onAngulationMenu($event)); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](4, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](6, "span", 8); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](8, "span", 9); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](9); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](10, "span", 10); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](12, VolumeViewportComponent_Conditional_1_Conditional_12_Template, 2, 1, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](13, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](14, VolumeViewportComponent_Conditional_1_Conditional_14_Template, 1, 4, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](15, VolumeViewportComponent_Conditional_1_Conditional_15_Template, 1, 2, "lib-viewport-button", 12); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](16, VolumeViewportComponent_Conditional_1_Conditional_16_Template, 1, 7, "ng-container"); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](17, "lib-viewport-button", 13); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("click", function VolumeViewportComponent_Conditional_1_Template_lib_viewport_button_click_17_listener() { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r2); const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx_r2.onToggleMaximizeViewport()); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()()()(); } if (rf & 2) { const ctx_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("ngTemplateOutlet", ctx_r2.annotationCardsTemplate()); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵclassProp"]("text-primary-300", ctx_r2.isPosterior()); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r2.angleLabel().raoLao.direction, " "); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r2.angleLabel().raoLao.formattedValue, " "); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r2.angleLabel().caudCran.direction, " "); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵtextInterpolate1"](" ", ctx_r2.angleLabel().caudCran.formattedValue, " "); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx_r2.angleLabel().isPosterior ? 12 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx_r2.settingsPopoverTemplate() ? 14 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx_r2.includeViewportSwap() && !ctx_r2.maximized() ? 15 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx_r2.includeViewportMenu() && ctx_r2.viewportSettingsPopoverTemplate() ? 16 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("tooltip", ctx_r2.maximized() ? ctx_r2.minimizeLabel() : ctx_r2.maximizeLabel())("ariaLabel", ctx_r2.maximized() ? ctx_r2.minimizeLabel() : ctx_r2.maximizeLabel())("icon", ctx_r2.maximized() ? "arrow-down-left-and-arrow-up-right-to-center" : "arrow-up-right-and-arrow-down-left-from-center"); } } class VolumeViewportComponent { translate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_4__.TranslateService); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.cn; state = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "state" }] : [])); label = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(...(ngDevMode ? [undefined, { debugName: "label" }] : [])); darkMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, ...(ngDevMode ? [{ debugName: "darkMode" }] : [])); maximized = _angular_core__WEBPACK_IMPORTED_MODULE_1__.input.required(...(ngDevMode ? [{ debugName: "maximized" }] : [])); includeViewportSwap = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(true, ...(ngDevMode ? [{ debugName: "includeViewportSwap" }] : [])); includeViewportMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "includeViewportMenu" }] : [])); annotationCardsTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "annotationCardsTemplate" }] : [])); settingsPopoverTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "settingsPopoverTemplate" }] : [])); viewportSettingsPopoverTemplate = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(undefined, ...(ngDevMode ? [{ debugName: "viewportSettingsPopoverTemplate" }] : [])); isPosterior = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "isPosterior" }] : [])); angulation = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)({ ax: 0, cc: 0, rl: 0 }, ...(ngDevMode ? [{ debugName: "angulation" }] : [])); swapLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(this.translate.instant('viewportButton.swapLabel'), ...(ngDevMode ? [{ debugName: "swapLabel" }] : [])); minimizeLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(this.translate.instant('viewportButton.minimizeLabel'), ...(ngDevMode ? [{ debugName: "minimizeLabel" }] : [])); maximizeLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(this.translate.instant('viewportButton.maximizeLabel'), ...(ngDevMode ? [{ debugName: "maximizeLabel" }] : [])); viewportSettingsLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(this.translate.instant('viewportButton.settingsLabel'), ...(ngDevMode ? [{ debugName: "viewportSettingsLabel" }] : [])); createMode = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)(false, ...(ngDevMode ? [{ debugName: "createMode" }] : [])); cursor = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.input)('', ...(ngDevMode ? [{ debugName: "cursor" }] : [])); viewportReady = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); viewportDestroyed = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); clicked = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); wheelScrolled = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); /** Safari-only trackpad gesture events. */ gestureStarted = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); gestureChanged = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); gestureEnded = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); mouseDown = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); mouseMove = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); contextMenu = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); perspectiveChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); toggleMaximizeViewport = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); focusedMPRViewportChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); angleLabelClick2 = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.output)(); container = _angular_core__WEBPACK_IMPORTED_MODULE_1__.viewChild.required('container'); angleLabel = (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.computed)(() => { const angulation = this.angulation(); const posterior = this.isPosterior(); return (0,_tomoverse_utils__WEBPACK_IMPORTED_MODULE_5__.formatAngulation)(angulation, posterior); }, ...(ngDevMode ? [{ debugName: "angleLabel" }] : [])); onClick(event) { this.clicked.emit(event); } onWheel(event) { this.wheelScrolled.emit(event); } onMouseDown(event) { this.mouseDown.emit(event); } onMouseMove(event) { this.mouseMove.emit(event); } onContextMenu(event) { this.contextMenu.emit({ event }); } onAngulationMenu(event) { this.contextMenu.emit({ event, key: 'angulationMenu' }); } onToggleMaximizeViewport() { this.toggleMaximizeViewport.emit(); } onFocusedMPRViewportChange() { this.focusedMPRViewportChange.emit(); } /** * Safari-only trackpad gesture (twist + pinch). */ handleGestureStart = event => { event.preventDefault(); this.gestureStarted.emit(event); }; handleGestureChange = event => { event.preventDefault(); this.gestureChanged.emit(event); }; handleGestureEnd = event => { event.preventDefault(); this.gestureEnded.emit(event); }; ngAfterViewInit() { const element = this.container().nativeElement; if ('GestureEvent' in globalThis) { element.addEventListener('gesturestart', this.handleGestureStart); element.addEventListener('gesturechange', this.handleGestureChange); element.addEventListener('gestureend', this.handleGestureEnd); } this.viewportReady.emit({ element, options: this.state() }); } ngOnDestroy() { const element = this.container().nativeElement; element.removeEventListener('gesturestart', this.handleGestureStart); element.removeEventListener('gesturechange', this.handleGestureChange); element.removeEventListener('gestureend', this.handleGestureEnd); this.viewportDestroyed.emit(this.state().id); } static ɵfac = function VolumeViewportComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || VolumeViewportComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵdefineComponent"]({ type: VolumeViewportComponent, selectors: [["lib-volume-viewport"]], viewQuery: function VolumeViewportComponent_Query(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵviewQuerySignal"](ctx.container, _c0, 5); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵqueryAdvance"](); } }, inputs: { state: [1, "state"], label: [1, "label"], darkMode: [1, "darkMode"], maximized: [1, "maximized"], includeViewportSwap: [1, "includeViewportSwap"], includeViewportMenu: [1, "includeViewportMenu"], annotationCardsTemplate: [1, "annotationCardsTemplate"], settingsPopoverTemplate: [1, "settingsPopoverTemplate"], viewportSettingsPopoverTemplate: [1, "viewportSettingsPopoverTemplate"], isPosterior: [1, "isPosterior"], angulation: [1, "angulation"], swapLabel: [1, "swapLabel"], minimizeLabel: [1, "minimizeLabel"], maximizeLabel: [1, "maximizeLabel"], viewportSettingsLabel: [1, "viewportSettingsLabel"], createMode: [1, "createMode"], cursor: [1, "cursor"] }, outputs: { viewportReady: "viewportReady", viewportDestroyed: "viewportDestroyed", clicked: "clicked", wheelScrolled: "wheelScrolled", gestureStarted: "gestureStarted", gestureChanged: "gestureChanged", gestureEnded: "gestureEnded", mouseDown: "mouseDown", mouseMove: "mouseMove", contextMenu: "contextMenu", perspectiveChange: "perspectiveChange", toggleMaximizeViewport: "toggleMaximizeViewport", focusedMPRViewportChange: "focusedMPRViewportChange", angleLabelClick2: "angleLabelClick2" }, ngContentSelectors: _c1, decls: 5, vars: 11, consts: [["container", ""], [1, "relative", "size-full", "bg-(--p-app-viewport-background)", 3, "id"], ["display", "inline-block", 1, "absolute", "bottom-0", "left-0", "z-10", "flex", "w-full", "flex-col", "gap-2", "py-2", "pr-2", "pl-6"], ["tabindex", "0", 3, "mousedown", "mousemove", "wheel", "click", "contextmenu", "keydown"], [4, "ngTemplateOutlet"], [1, "flex", "h-8", "items-center", "justify-between", "gap-1", "text-(--p-app-viewport-label)"], [1, "text-md", "focus:outline-primary-300", "flex", "items-center", "gap-1", "rounded", "px-2", "text-left", "text-(--p-app-viewport-label)", "transition-colors", "text-shadow-[0_0_3px_var(--p-app-viewport-outline),0_0_3px_var(--p-app-viewport-outline)]", "focus:outline", 3, "contextmenu"], [1, "inline-block", "w-5", "text-left"], [1, "inline-block", "w-10", "text-right"], [1, "inline-block", "w-8", "text-left"], [1, "inline-block", "w-9.5", "text-right"], [1, "flex", "gap-1"], ["tooltipPosition", "top", "icon", "swap", "iconClass", "size-(--p-app-icon-size-xs) [filter:drop-shadow(0_0_1px_var(--p-app-viewport-outline))_drop-shadow(0_0_1px_var(--p-app-viewport-outline))]", 3, "tooltip", "ariaLabel"], ["tooltipPosition", "left", "iconType", "prime", 3, "click", "tooltip", "ariaLabel", "icon"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], ["tooltipPosition", "top", "icon", "swap", "iconClass", "size-(--p-app-icon-size-xs) [filter:drop-shadow(0_0_1px_var(--p-app-viewport-outline))_drop-shadow(0_0_1px_var(--p-app-viewport-outline))]", 3, "click", "tooltip", "ariaLabel"]], template: function VolumeViewportComponent_Template(rf, ctx) { if (rf & 1) { const _r1 = _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵgetCurrentView"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵprojectionDef"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](0, "div", 1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditionalCreate"](1, VolumeViewportComponent_Conditional_1_Template, 18, 14, "div", 2); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementStart"](2, "div", 3, 0); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵlistener"]("mousedown", function VolumeViewportComponent_Template_div_mousedown_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onMouseDown($event)); })("mousemove", function VolumeViewportComponent_Template_div_mousemove_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onMouseMove($event)); })("wheel", function VolumeViewportComponent_Template_div_wheel_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onWheel($event)); })("click", function VolumeViewportComponent_Template_div_click_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onClick($event)); })("contextmenu", function VolumeViewportComponent_Template_div_contextmenu_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"](ctx.onContextMenu($event)); })("keydown", function VolumeViewportComponent_Template_div_keydown_2_listener($event) { _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵrestoreView"](_r1); return _angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵresetView"]($event.preventDefault()); }); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵprojection"](4); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵelementEnd"]()(); } if (rf & 2) { _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵproperty"]("id", ctx.state().id); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵattribute"]("data-test-id", `volume-viewport-div-container-${ctx.state().id}`); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵconditional"](ctx.state() ? 1 : -1); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵclassMap"](_angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵpureFunction1"](9, _c2, ctx.createMode() ? "cursor-crosshair!" : ctx.cursor() ? "" : "cursor-default!")); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵstyleProp"]("cursor", ctx.cursor() || null); _angular_core__WEBPACK_IMPORTED_MODULE_7__["ɵɵattribute"]("aria-label", "Medical image viewport: " + ctx.state().id)("data-test-id", `volume-viewport-div-${ctx.state().id}`); } }, dependencies: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.NgTemplateOutlet, _viewport_button_viewport_button_component__WEBPACK_IMPORTED_MODULE_6__.ViewportButtonComponent], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 41216 /*!************************************************************************!*\ !*** ./libs/ui/src/lib/work-session-tab/work-session-tab.component.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ WorkSessionTabComponent: () => (/* binding */ WorkSessionTabComponent) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var primeng_divider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! primeng/divider */ 1432); /* harmony import */ var primeng_tag__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! primeng/tag */ 37587); /* harmony import */ var primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! primeng/tooltip */ 30642); /* harmony import */ var _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @tomoverse/utils */ 49585); /* harmony import */ var _icon_icon_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../icon/icon.component */ 92242); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 14975); const _c0 = () => ({ display: "none" }); const _c1 = a0 => ({ style: a0 }); const _c2 = a0 => ({ arrow: a0, root: "mt-2 min-w-72 max-w-96 shadow-xl" }); const _c3 = () => ({ background: "{content.background}", borderRadius: "var(--p-border-radius-md)" }); const _c4 = () => ({ root: "leading-none whitespace-nowrap p-1 font-semibold" }); const _c5 = () => ({ fontSize: "0.6rem" }); const _c6 = a0 => ({ root: a0 }); const _c7 = () => ({ margin: 0 }); const _c8 = a0 => ({ horizontal: a0 }); function WorkSessionTabComponent_ng_template_11_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 8)(1, "div", 9)(2, "span", 10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](4, "span", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](6, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](7); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](8, "p-divider", 12); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](9, "div")(10, "div", 10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](12, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](13); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](14, "div", 11); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](15); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()()(); } if (rf & 2) { const ctx_r0 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵnextContext"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx_r0.details().patient.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate2"](" (", ctx_r0.details().patient.gender, ") \u2022 MRN: ", ctx_r0.details().patient.mrn, " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"]("DOB: ", ctx_r0.details().patient.birthdate); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("dt", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](10, _c8, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](9, _c7))); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](ctx_r0.details().description); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate2"]("", ctx_r0.details().date, " \u2022 ", ctx_r0.details().time); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate"](ctx_r0.details().modality); } } class WorkSessionTabComponent { details = _angular_core__WEBPACK_IMPORTED_MODULE_0__.input.required(...(ngDevMode ? [{ debugName: "details" }] : [])); mutedTextPt = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.input)(...(ngDevMode ? [undefined, { debugName: "mutedTextPt" }] : [])); cn = _tomoverse_utils__WEBPACK_IMPORTED_MODULE_4__.cn; static ɵfac = function WorkSessionTabComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || WorkSessionTabComponent)(); }; static ɵcmp = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵdefineComponent"]({ type: WorkSessionTabComponent, selectors: [["lib-work-session-tab"]], inputs: { details: [1, "details"], mutedTextPt: [1, "mutedTextPt"] }, decls: 13, vars: 22, consts: [["tooltipContent", ""], [1, "flex", "w-full", "min-w-0", "items-center", "gap-2"], ["tooltipPosition", "bottom", 1, "flex", "min-w-0", "flex-col", "py-1", 3, "pTooltip", "pTooltipPT", "dt"], [1, "flex", "w-full", "gap-1.5"], ["size", "small", "severity", "contrast", 1, "invert", 3, "value", "pt", "dt"], [1, "truncate", "text-xs", "font-semibold"], ["icon", "user", "iconClass", "text-xs ml-auto"], [1, "truncate", "text-xs"], [1, "flex", "flex-col", "gap-1", "text-[.7rem]"], [1, "flex", "items-center", "gap-2"], [1, "text-xs", "font-semibold"], [1, "text-muted-color"], [1, "mt-1", 3, "dt"]], template: function WorkSessionTabComponent_Template(rf, ctx) { if (rf & 1) { _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](0, "div", 1)(1, "div", 2)(2, "div", 3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](3, "p-tag", 4); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](4, "span", 5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](5); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelement"](6, "lib-icon", 6); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](7, "span", 7); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](8); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementStart"](9, "span"); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtext"](10); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵelementEnd"]()()(); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplate"](11, WorkSessionTabComponent_ng_template_11_Template, 16, 12, "ng-template", null, 0, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtemplateRefExtractor"]); } if (rf & 2) { const tooltipContent_r2 = _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵreference"](12); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("pTooltip", tooltipContent_r2)("pTooltipPT", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](15, _c2, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](13, _c1, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](12, _c0))))("dt", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](17, _c3)); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵproperty"]("value", ctx.details().modalityTag)("pt", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](18, _c4))("dt", _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction1"](20, _c6, _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵpureFunction0"](19, _c5))); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](2); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx.details().name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](3); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate1"](" ", ctx.details().patient.name, " "); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵclassMap"](ctx.cn("text-muted-color truncate text-[0.625rem]", ctx.mutedTextPt())); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵadvance"](); _angular_core__WEBPACK_IMPORTED_MODULE_6__["ɵɵtextInterpolate2"](" ", ctx.details().date, " \u2022 ", ctx.details().description, " "); } }, dependencies: [_icon_icon_component__WEBPACK_IMPORTED_MODULE_5__.IconComponent, primeng_tooltip__WEBPACK_IMPORTED_MODULE_3__.Tooltip, primeng_tag__WEBPACK_IMPORTED_MODULE_2__.Tag, primeng_divider__WEBPACK_IMPORTED_MODULE_1__.Divider], encapsulation: 2, changeDetection: 0 }); } /***/ }, /***/ 49585 /*!*********************************!*\ !*** ./libs/utils/src/index.ts ***! \*********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ANALYSIS_BASE_NAME: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.ANALYSIS_BASE_NAME), /* harmony export */ ANNOTATION_NAME_MAX_LENGTH: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.ANNOTATION_NAME_MAX_LENGTH), /* harmony export */ ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA), /* harmony export */ ANNOTATION_STRUCTURE_NAMES: () => (/* reexport safe */ _lib_annotation_structure_names__WEBPACK_IMPORTED_MODULE_2__.ANNOTATION_STRUCTURE_NAMES), /* harmony export */ ANNOTATION_VISIBLE_DISTANCE_MM: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.ANNOTATION_VISIBLE_DISTANCE_MM), /* harmony export */ BASE_MPR_WL_PRESETS: () => (/* reexport safe */ _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__.BASE_MPR_WL_PRESETS), /* harmony export */ CHAMBER_NAME_MAX_LENGTH: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.CHAMBER_NAME_MAX_LENGTH), /* harmony export */ CHAMBER_STRUCTURE_NAMES: () => (/* reexport safe */ _lib_chamber_structure_names__WEBPACK_IMPORTED_MODULE_3__.CHAMBER_STRUCTURE_NAMES), /* harmony export */ CLIP_FACE_TARGET_LINE: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.CLIP_FACE_TARGET_LINE), /* harmony export */ CUSTOM_COLOR_MIX_ANCHOR: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.CUSTOM_COLOR_MIX_ANCHOR), /* harmony export */ CornerstoneInitService: () => (/* reexport safe */ _lib_cornerstone_cornerstone_init_service__WEBPACK_IMPORTED_MODULE_41__.CornerstoneInitService), /* harmony export */ DEBUG_FLAGS: () => (/* reexport safe */ _lib_debug__WEBPACK_IMPORTED_MODULE_72__.DEBUG_FLAGS), /* harmony export */ DEFAULT_CROSSHAIR_SIZE: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_CROSSHAIR_SIZE), /* harmony export */ DEFAULT_MAX_PIXELS: () => (/* reexport safe */ _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__.DEFAULT_MAX_PIXELS), /* harmony export */ DEFAULT_PRESET_NAME: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_PRESET_NAME), /* harmony export */ DEFAULT_SAMPLE_DISTANCE_MULTIPLIER: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_SAMPLE_DISTANCE_MULTIPLIER), /* harmony export */ DEFAULT_VIEWPORT_CONFIG: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_VIEWPORT_CONFIG), /* harmony export */ DEFAULT_VOLUME_RENDERING_PRESET: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_VOLUME_RENDERING_PRESET), /* harmony export */ DEFAULT_WINDOW_PRESET: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DEFAULT_WINDOW_PRESET), /* harmony export */ DICOM_DATE_FORMAT: () => (/* reexport safe */ _lib_pipes_dicom_date_pipe__WEBPACK_IMPORTED_MODULE_36__.DICOM_DATE_FORMAT), /* harmony export */ DICOM_DATE_TIME_FORMAT: () => (/* reexport safe */ _lib_pipes_dicom_date_pipe__WEBPACK_IMPORTED_MODULE_36__.DICOM_DATE_TIME_FORMAT), /* harmony export */ DICOM_IMAGE_LOADER: () => (/* reexport safe */ _lib_dicom_dicom_image_loader_token__WEBPACK_IMPORTED_MODULE_56__.DICOM_IMAGE_LOADER), /* harmony export */ DICOM_IMPORTER_TABLE_COLUMN_CONFIG: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.DICOM_IMPORTER_TABLE_COLUMN_CONFIG), /* harmony export */ DicomDatePipe: () => (/* reexport safe */ _lib_pipes_dicom_date_pipe__WEBPACK_IMPORTED_MODULE_36__.DicomDatePipe), /* harmony export */ DicomPersonNamePipe: () => (/* reexport safe */ _lib_pipes_dicom_person_name_pipe__WEBPACK_IMPORTED_MODULE_37__.DicomPersonNamePipe), /* harmony export */ ENDO_KEY_LIGHT_ELEVATION: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.ENDO_KEY_LIGHT_ELEVATION), /* harmony export */ ENV: () => (/* reexport safe */ _lib_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_39__.ENV), /* harmony export */ FLUORO_ATTENUATION_PER_MM: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.FLUORO_ATTENUATION_PER_MM), /* harmony export */ FLUORO_REF_MAX_HU: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.FLUORO_REF_MAX_HU), /* harmony export */ FLUORO_REF_MIN_HU: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.FLUORO_REF_MIN_HU), /* harmony export */ INIT_CAMERA_MATRIX: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.INIT_CAMERA_MATRIX), /* harmony export */ IS_DEV_BUILD: () => (/* reexport safe */ _lib_injection_tokens_is_dev_build_injection_token__WEBPACK_IMPORTED_MODULE_40__.IS_DEV_BUILD), /* harmony export */ LOW_SAMPLE_DISTANCE_MULTIPLIER: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.LOW_SAMPLE_DISTANCE_MULTIPLIER), /* harmony export */ MAX_RECENT_WORK_SESSIONS: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.MAX_RECENT_WORK_SESSIONS), /* harmony export */ MODALITY_CT_ERROR_MESSAGE: () => (/* reexport safe */ _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__.MODALITY_CT_ERROR_MESSAGE), /* harmony export */ NO_DATA_PLACEHOLDER: () => (/* reexport safe */ _lib_pipes_or_dash_pipe__WEBPACK_IMPORTED_MODULE_38__.NO_DATA_PLACEHOLDER), /* harmony export */ ORIGIN: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.ORIGIN), /* harmony export */ OrDashPipe: () => (/* reexport safe */ _lib_pipes_or_dash_pipe__WEBPACK_IMPORTED_MODULE_38__.OrDashPipe), /* harmony export */ PRESET_NAME_PREFIX: () => (/* reexport safe */ _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__.PRESET_NAME_PREFIX), /* harmony export */ RADON_COLOR_TARGET_LINE: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.RADON_COLOR_TARGET_LINE), /* harmony export */ TOMOVERSE_IMAGE_VOLUME_SCHEME: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.TOMOVERSE_IMAGE_VOLUME_SCHEME), /* harmony export */ TRANSPARENT_SAMPLE_TARGET_LINE: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.TRANSPARENT_SAMPLE_TARGET_LINE), /* harmony export */ TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE), /* harmony export */ UNINIT: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.UNINIT), /* harmony export */ VASCULAR_MASK_LABELS: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.VASCULAR_MASK_LABELS), /* harmony export */ VOLUME_RENDERING_PRESETS: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.VOLUME_RENDERING_PRESETS), /* harmony export */ WORK_SESSION_CREATED_STATE_KEY: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.WORK_SESSION_CREATED_STATE_KEY), /* harmony export */ WORK_SESSION_NEW_KEY: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.WORK_SESSION_NEW_KEY), /* harmony export */ aabbCentreDepth: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbCentreDepth), /* harmony export */ aabbFromVec3s: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbFromVec3s), /* harmony export */ aabbFromVertices: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbFromVertices), /* harmony export */ aabbOverlap: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbOverlap), /* harmony export */ aabbRayIntersect: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbRayIntersect), /* harmony export */ aabbToVec3s: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbToVec3s), /* harmony export */ aabbVolume: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.aabbVolume), /* harmony export */ acceptVascularPreview: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.acceptVascularPreview), /* harmony export */ addActorToViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.addActorToViewport), /* harmony export */ addAndActivateToolsToGroup: () => (/* reexport safe */ _lib_cornerstone_cornerstone_tool_group__WEBPACK_IMPORTED_MODULE_42__.addAndActivateToolsToGroup), /* harmony export */ addAnnotationActor: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.addAnnotationActor), /* harmony export */ addAnnotationGhostActor: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.addAnnotationGhostActor), /* harmony export */ addPointToSpline: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.addPointToSpline), /* harmony export */ adjustProximalAndDistalClippingPlanes: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.adjustProximalAndDistalClippingPlanes), /* harmony export */ alignAxisOfSymmetryToView: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.alignAxisOfSymmetryToView), /* harmony export */ allScurveTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.allScurveTypes), /* harmony export */ allSplineTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.allSplineTypes), /* harmony export */ angleTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.angleTypes), /* harmony export */ angulationFromOrientation: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.angulationFromOrientation), /* harmony export */ angulationToVector: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.angulationToVector), /* harmony export */ annotationMapper: () => (/* reexport safe */ _lib_vtk_mappers__WEBPACK_IMPORTED_MODULE_52__.annotationMapper), /* harmony export */ annotationPointInBand: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.annotationPointInBand), /* harmony export */ applyAnnotationActorLighting: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyAnnotationActorLighting), /* harmony export */ applyAnnotationLighting: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyAnnotationLighting), /* harmony export */ applyEndoPresetToViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyEndoPresetToViewport), /* harmony export */ applyFluoroscopicPresetToViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyFluoroscopicPresetToViewport), /* harmony export */ applyImageSampleDistance: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyImageSampleDistance), /* harmony export */ applyMipPresetToViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyMipPresetToViewport), /* harmony export */ applyVascularPresetToViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyVascularPresetToViewport), /* harmony export */ applyVascularRegionMask: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyVascularRegionMask), /* harmony export */ applyVolume3dSampleDistance: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.applyVolume3dSampleDistance), /* harmony export */ attachVascularGpuMask: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.attachVascularGpuMask), /* harmony export */ attachedProjectionCurve: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.attachedProjectionCurve), /* harmony export */ autoAlignAxis: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.autoAlignAxis), /* harmony export */ autoSeedFromVolume: () => (/* reexport safe */ _lib_segmentation_region_growing__WEBPACK_IMPORTED_MODULE_51__.autoSeedFromVolume), /* harmony export */ automatedTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.automatedTypes), /* harmony export */ buildDicomPresets: () => (/* reexport safe */ _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__.buildDicomPresets), /* harmony export */ buildObject3dTransform: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.buildObject3dTransform), /* harmony export */ buildOctree: () => (/* reexport safe */ _lib_geometry_octree__WEBPACK_IMPORTED_MODULE_71__.buildOctree), /* harmony export */ buildSeriesWindowState: () => (/* reexport safe */ _lib_volume_viewer_build_series_window_state__WEBPACK_IMPORTED_MODULE_66__.buildSeriesWindowState), /* harmony export */ buildSvgPath: () => (/* reexport safe */ _lib_svg__WEBPACK_IMPORTED_MODULE_31__.buildSvgPath), /* harmony export */ buildWindowDefaults: () => (/* reexport safe */ _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__.buildWindowDefaults), /* harmony export */ calculateAngleBetweenPoints: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateAngleBetweenPoints), /* harmony export */ calculateClosedSplineArea: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateClosedSplineArea), /* harmony export */ calculateClosedSplineBestFitNormal: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateClosedSplineBestFitNormal), /* harmony export */ calculateClosedSplineHeight: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateClosedSplineHeight), /* harmony export */ calculateCurvatureRadius: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateCurvatureRadius), /* harmony export */ calculateCylinderGeometry: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateCylinderGeometry), /* harmony export */ calculateDistanceBetweenPoints: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateDistanceBetweenPoints), /* harmony export */ calculateDistanceOnPath: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateDistanceOnPath), /* harmony export */ calculateHollowCylinderGeometry: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateHollowCylinderGeometry), /* harmony export */ calculatePathDistance: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculatePathDistance), /* harmony export */ calculatePathMaximumDiameter: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculatePathMaximumDiameter), /* harmony export */ calculatePointsOnAxis: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculatePointsOnAxis), /* harmony export */ calculateSplinePath: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateSplinePath), /* harmony export */ cameraStateAtProgress: () => (/* reexport safe */ _lib_volume_viewer_camera_interpolation__WEBPACK_IMPORTED_MODULE_68__.cameraStateAtProgress), /* harmony export */ cancelVascularFullRun: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.cancelVascularFullRun), /* harmony export */ clampOffsetWithinBounds: () => (/* reexport safe */ _lib_drag_bounds__WEBPACK_IMPORTED_MODULE_14__.clampOffsetWithinBounds), /* harmony export */ clampRange: () => (/* reexport safe */ _lib_clamp_range__WEBPACK_IMPORTED_MODULE_9__.clampRange), /* harmony export */ clearViewportWidgets: () => (/* reexport safe */ _lib_cornerstone_viewport_widgets__WEBPACK_IMPORTED_MODULE_48__.clearViewportWidgets), /* harmony export */ clickInfo: () => (/* reexport safe */ _lib_click_info__WEBPACK_IMPORTED_MODULE_10__.clickInfo), /* harmony export */ closedSpline: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.closedSpline), /* harmony export */ closestPathPointToRay: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.closestPathPointToRay), /* harmony export */ closestPointsBetweenPaths: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.closestPointsBetweenPaths), /* harmony export */ cn: () => (/* reexport safe */ _lib_cn__WEBPACK_IMPORTED_MODULE_11__.cn), /* harmony export */ colorNotEditableTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.colorNotEditableTypes), /* harmony export */ compileShader: () => (/* reexport safe */ _lib_webgl_program__WEBPACK_IMPORTED_MODULE_55__.compileShader), /* harmony export */ computeAutoVascularThresholdsForVolume: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.computeAutoVascularThresholdsForVolume), /* harmony export */ computeConvexHull: () => (/* reexport safe */ _lib_geometry_convex_hull__WEBPACK_IMPORTED_MODULE_70__.computeConvexHull), /* harmony export */ computeImageSampleDistance: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.computeImageSampleDistance), /* harmony export */ computeThrottled: () => (/* reexport safe */ _lib_signals__WEBPACK_IMPORTED_MODULE_30__.computeThrottled), /* harmony export */ computeVascularThresholdsFromMask: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.computeVascularThresholdsFromMask), /* harmony export */ configureAnnotationActorLighting: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.configureAnnotationActorLighting), /* harmony export */ cssVariableToNormalizedRgb: () => (/* reexport safe */ _lib_colors__WEBPACK_IMPORTED_MODULE_12__.cssVariableToNormalizedRgb), /* harmony export */ cubicInterpolator: () => (/* reexport safe */ _lib_interpolation__WEBPACK_IMPORTED_MODULE_21__.cubicInterpolator), /* harmony export */ debounce: () => (/* reexport safe */ _lib_throttle_debounce__WEBPACK_IMPORTED_MODULE_32__.debounce), /* harmony export */ decacheVolumeIds: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.decacheVolumeIds), /* harmony export */ declutterLabels: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.declutterLabels), /* harmony export */ defaultRxdbConfig: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.defaultRxdbConfig), /* harmony export */ deg2rad: () => (/* reexport safe */ _lib_angles__WEBPACK_IMPORTED_MODULE_0__.deg2rad), /* harmony export */ describePhase: () => (/* reexport safe */ _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__.describePhase), /* harmony export */ deserializeObject3DGeometry: () => (/* reexport safe */ _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__.deserializeObject3DGeometry), /* harmony export */ detachAnnotationOverlay: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.detachAnnotationOverlay), /* harmony export */ detachVascularGpuMask: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.detachVascularGpuMask), /* harmony export */ distanceTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.distanceTypes), /* harmony export */ exportFromImageVolume: () => (/* reexport safe */ _lib_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_44__.exportFromImageVolume), /* harmony export */ exportToJsonFile: () => (/* reexport safe */ _lib_export_json__WEBPACK_IMPORTED_MODULE_15__.exportToJsonFile), /* harmony export */ exportVolumeGeometry: () => (/* reexport safe */ _lib_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_44__.exportVolumeGeometry), /* harmony export */ extractDicomPart10: () => (/* reexport safe */ _lib_dicom_extract_dicom10__WEBPACK_IMPORTED_MODULE_57__.extractDicomPart10), /* harmony export */ extractPixelData: () => (/* reexport safe */ _lib_dicom_extract_pixel_data__WEBPACK_IMPORTED_MODULE_60__.extractPixelData), /* harmony export */ extractWindowMetadata: () => (/* reexport safe */ _lib_dicom_extract_window_metadata__WEBPACK_IMPORTED_MODULE_58__.extractWindowMetadata), /* harmony export */ findActorInArea: () => (/* reexport safe */ _lib_cornerstone_hardware_selector__WEBPACK_IMPORTED_MODULE_50__.findActorInArea), /* harmony export */ flipAxisOfSymmetry: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.flipAxisOfSymmetry), /* harmony export */ fluoroOpacityGain: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.fluoroOpacityGain), /* harmony export */ formatAngulation: () => (/* reexport safe */ _lib_angulation__WEBPACK_IMPORTED_MODULE_1__.formatAngulation), /* harmony export */ formatAngulationtxt: () => (/* reexport safe */ _lib_angulation__WEBPACK_IMPORTED_MODULE_1__.formatAngulationtxt), /* harmony export */ formatCaudCran: () => (/* reexport safe */ _lib_angulation__WEBPACK_IMPORTED_MODULE_1__.formatCaudCran), /* harmony export */ formatExportFileName: () => (/* reexport safe */ _lib_format_export_filename__WEBPACK_IMPORTED_MODULE_16__.formatExportFileName), /* harmony export */ formatPhaseIdentification: () => (/* reexport safe */ _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__.formatPhaseIdentification), /* harmony export */ formatRaoLao: () => (/* reexport safe */ _lib_angulation__WEBPACK_IMPORTED_MODULE_1__.formatRaoLao), /* harmony export */ fragmentReplacement: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.fragmentReplacement), /* harmony export */ generateUniqueName: () => (/* reexport safe */ _lib_generate_unique_name__WEBPACK_IMPORTED_MODULE_17__.generateUniqueName), /* harmony export */ getAllDebugFlags: () => (/* reexport safe */ _lib_debug__WEBPACK_IMPORTED_MODULE_72__.getAllDebugFlags), /* harmony export */ getAnnotationActor: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.getAnnotationActor), /* harmony export */ getAnnotationActors: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.getAnnotationActors), /* harmony export */ getAnnotationOverlayRenderer: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.getAnnotationOverlayRenderer), /* harmony export */ getAtIJK: () => (/* reexport safe */ _lib_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_44__.getAtIJK), /* harmony export */ getDebugFlagByName: () => (/* reexport safe */ _lib_debug__WEBPACK_IMPORTED_MODULE_72__.getDebugFlagByName), /* harmony export */ getDefaultViewport: () => (/* reexport safe */ _lib_volume_viewer_default_viewport_config__WEBPACK_IMPORTED_MODULE_65__.getDefaultViewport), /* harmony export */ getMprViewport: () => (/* reexport safe */ _lib_cornerstone_viewport_types__WEBPACK_IMPORTED_MODULE_47__.getMprViewport), /* harmony export */ getOrRegisterNewToolGroup: () => (/* reexport safe */ _lib_cornerstone_cornerstone_tool_group__WEBPACK_IMPORTED_MODULE_42__.getOrRegisterNewToolGroup), /* harmony export */ getPointAtDistance: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.getPointAtDistance), /* harmony export */ getPrimaryImageVolume: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.getPrimaryImageVolume), /* harmony export */ getVascularMaskLabels: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.getVascularMaskLabels), /* harmony export */ getViewport: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.getViewport), /* harmony export */ getVolumeActor: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.getVolumeActor), /* harmony export */ getVolumeScalarRange: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.getVolumeScalarRange), /* harmony export */ hasDisplayValue: () => (/* reexport safe */ _lib_pipes_or_dash_pipe__WEBPACK_IMPORTED_MODULE_38__.hasDisplayValue), /* harmony export */ hasVolumeActor: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.hasVolumeActor), /* harmony export */ hashObject3DGeometry: () => (/* reexport safe */ _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__.hashObject3DGeometry), /* harmony export */ hexToNormalizedRgb: () => (/* reexport safe */ _lib_colors__WEBPACK_IMPORTED_MODULE_12__.hexToNormalizedRgb), /* harmony export */ importFromJsonFile: () => (/* reexport safe */ _lib_import_json__WEBPACK_IMPORTED_MODULE_19__.importFromJsonFile), /* harmony export */ incrementName: () => (/* reexport safe */ _lib_increment_name__WEBPACK_IMPORTED_MODULE_20__.incrementName), /* harmony export */ initAnnotationOverlay: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.initAnnotationOverlay), /* harmony export */ installTransparentSampleEarlyOut: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.installTransparentSampleEarlyOut), /* harmony export */ instantlyReapplyVascularMask: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.instantlyReapplyVascularMask), /* harmony export */ isBaseVolumeViewportLike: () => (/* reexport safe */ _lib_cornerstone_viewport_types__WEBPACK_IMPORTED_MODULE_47__.isBaseVolumeViewportLike), /* harmony export */ isDoubleClick: () => (/* reexport safe */ _lib_click_info__WEBPACK_IMPORTED_MODULE_10__.isDoubleClick), /* harmony export */ isEditableTarget: () => (/* reexport safe */ _lib_browser_keyboard_targets__WEBPACK_IMPORTED_MODULE_5__.isEditableTarget), /* harmony export */ isEqualSet: () => (/* reexport safe */ _lib_is_equal_set__WEBPACK_IMPORTED_MODULE_34__.isEqualSet), /* harmony export */ isInteractiveTarget: () => (/* reexport safe */ _lib_browser_keyboard_targets__WEBPACK_IMPORTED_MODULE_5__.isInteractiveTarget), /* harmony export */ isValidBackendApiUrl: () => (/* reexport safe */ _lib_backend_api_url__WEBPACK_IMPORTED_MODULE_7__.isValidBackendApiUrl), /* harmony export */ isVascularGpuMaskAttached: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.isVascularGpuMaskAttached), /* harmony export */ isVascularGpuMaskExact: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.isVascularGpuMaskExact), /* harmony export */ isViewableModality: () => (/* reexport safe */ _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__.isViewableModality), /* harmony export */ isVtkVolumeMapper: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.isVtkVolumeMapper), /* harmony export */ lastDefined: () => (/* reexport safe */ _lib_signals__WEBPACK_IMPORTED_MODULE_30__.lastDefined), /* harmony export */ linearInterpolationByDistance2D: () => (/* reexport safe */ _lib_interpolation__WEBPACK_IMPORTED_MODULE_21__.linearInterpolationByDistance2D), /* harmony export */ linkProgram: () => (/* reexport safe */ _lib_webgl_program__WEBPACK_IMPORTED_MODULE_55__.linkProgram), /* harmony export */ loadVolumeImages: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.loadVolumeImages), /* harmony export */ looksMultiphase: () => (/* reexport safe */ _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__.looksMultiphase), /* harmony export */ makeObject3DGeometryBlob: () => (/* reexport safe */ _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__.makeObject3DGeometryBlob), /* harmony export */ mapViewportIdToOrientation: () => (/* reexport safe */ _lib_volume_viewer_map_viewport_to_orientation__WEBPACK_IMPORTED_MODULE_67__.mapViewportIdToOrientation), /* harmony export */ mat3ToArray: () => (/* reexport safe */ _lib_matrix__WEBPACK_IMPORTED_MODULE_22__.mat3ToArray), /* harmony export */ memoize: () => (/* reexport safe */ _lib_memoization__WEBPACK_IMPORTED_MODULE_23__.memoize), /* harmony export */ memoizeByReference: () => (/* reexport safe */ _lib_memoization__WEBPACK_IMPORTED_MODULE_23__.memoizeByReference), /* harmony export */ minDistanceToAABB: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.minDistanceToAABB), /* harmony export */ modelTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.modelTypes), /* harmony export */ mostDistinctAxis: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.mostDistinctAxis), /* harmony export */ nameNotEditableTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.nameNotEditableTypes), /* harmony export */ namesForToolTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.namesForToolTypes), /* harmony export */ noVisibilityTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.noVisibilityTypes), /* harmony export */ normalizeBackendApiUrl: () => (/* reexport safe */ _lib_backend_api_url__WEBPACK_IMPORTED_MODULE_7__.normalizeBackendApiUrl), /* harmony export */ normalizeModality: () => (/* reexport safe */ _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__.normalizeModality), /* harmony export */ normalizeSeriesUid: () => (/* reexport safe */ _lib_dicom_normalize_series_uid__WEBPACK_IMPORTED_MODULE_64__.normalizeSeriesUid), /* harmony export */ notDeletableTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.notDeletableTypes), /* harmony export */ object3dSymmetryAxis: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.object3dSymmetryAxis), /* harmony export */ orientationFromAngulation: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.orientationFromAngulation), /* harmony export */ parseDicomDate: () => (/* reexport safe */ _lib_dicom_parse_dicom_date_helper__WEBPACK_IMPORTED_MODULE_61__.parseDicomDate), /* harmony export */ parseHexColor: () => (/* reexport safe */ _lib_colors__WEBPACK_IMPORTED_MODULE_12__.parseHexColor), /* harmony export */ parsePosition: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.parsePosition), /* harmony export */ parseSTL: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.parseSTL), /* harmony export */ pickFileFromDisk: () => (/* reexport safe */ _lib_pick_file_from_disk__WEBPACK_IMPORTED_MODULE_26__.pickFileFromDisk), /* harmony export */ pickFromOverlay: () => (/* reexport safe */ _lib_cornerstone_hardware_selector__WEBPACK_IMPORTED_MODULE_50__.pickFromOverlay), /* harmony export */ pickFromVolume3DPrimary: () => (/* reexport safe */ _lib_cornerstone_hardware_selector__WEBPACK_IMPORTED_MODULE_50__.pickFromVolume3DPrimary), /* harmony export */ planeTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.planeTypes), /* harmony export */ pointTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.pointTypes), /* harmony export */ position: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.position), /* harmony export */ positionIsUninitialized: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.positionIsUninitialized), /* harmony export */ positionToVec3: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.positionToVec3), /* harmony export */ positionsEqual: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.positionsEqual), /* harmony export */ previewVascularRegionMask: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.previewVascularRegionMask), /* harmony export */ previewVascularRegionMaskLive: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.previewVascularRegionMaskLive), /* harmony export */ projectPointOnGeometry: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.projectPointOnGeometry), /* harmony export */ projectPointOnOctree: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.projectPointOnOctree), /* harmony export */ projectPointOnPlane: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.projectPointOnPlane), /* harmony export */ projectedAabbArea: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.projectedAabbArea), /* harmony export */ projectedAabbBounds2d: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.projectedAabbBounds2d), /* harmony export */ projectionCurveAngle: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.projectionCurveAngle), /* harmony export */ projectionCurveIntersection: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.projectionCurveIntersection), /* harmony export */ rad2deg: () => (/* reexport safe */ _lib_angles__WEBPACK_IMPORTED_MODULE_0__.rad2deg), /* harmony export */ raiseViewportKeyLight: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.raiseViewportKeyLight), /* harmony export */ randomColor: () => (/* reexport safe */ _lib_colors__WEBPACK_IMPORTED_MODULE_12__.randomColor), /* harmony export */ range: () => (/* reexport safe */ _lib_range__WEBPACK_IMPORTED_MODULE_29__.range), /* harmony export */ rayFromCamera: () => (/* reexport safe */ _lib_cornerstone_viewport_rays__WEBPACK_IMPORTED_MODULE_49__.rayFromCamera), /* harmony export */ rayFromSlicePlane: () => (/* reexport safe */ _lib_cornerstone_viewport_rays__WEBPACK_IMPORTED_MODULE_49__.rayFromSlicePlane), /* harmony export */ readObject3DGeometryBlob: () => (/* reexport safe */ _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__.readObject3DGeometryBlob), /* harmony export */ realScalarRangeByVolumeId: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.realScalarRangeByVolumeId), /* harmony export */ registerCornerstoneTools: () => (/* reexport safe */ _lib_cornerstone_cornerstone_tool_group__WEBPACK_IMPORTED_MODULE_42__.registerCornerstoneTools), /* harmony export */ registerToolGroupForViewports: () => (/* reexport safe */ _lib_cornerstone_cornerstone_tool_group__WEBPACK_IMPORTED_MODULE_42__.registerToolGroupForViewports), /* harmony export */ relativeTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.relativeTypes), /* harmony export */ releaseVascularWorkers: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.releaseVascularWorkers), /* harmony export */ removeAnnotationActor: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.removeAnnotationActor), /* harmony export */ removeAnnotationGhostActor: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.removeAnnotationGhostActor), /* harmony export */ removeShaderCallback: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.removeShaderCallback), /* harmony export */ removeShaderReplacement: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.removeShaderReplacement), /* harmony export */ removeViewportWidget: () => (/* reexport safe */ _lib_cornerstone_viewport_widgets__WEBPACK_IMPORTED_MODULE_48__.removeViewportWidget), /* harmony export */ resetAnnotationOverlaysForTest: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.resetAnnotationOverlaysForTest), /* harmony export */ resolveBoundaryRect: () => (/* reexport safe */ _lib_drag_bounds__WEBPACK_IMPORTED_MODULE_14__.resolveBoundaryRect), /* harmony export */ resolveSeedIJK: () => (/* reexport safe */ _lib_segmentation_region_growing__WEBPACK_IMPORTED_MODULE_51__.resolveSeedIJK), /* harmony export */ restoreVascularForPresetSwitch: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.restoreVascularForPresetSwitch), /* harmony export */ restoreVascularRegionMask: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.restoreVascularRegionMask), /* harmony export */ restoreViewportLightsToCameraLight: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.restoreViewportLightsToCameraLight), /* harmony export */ resyncAnnotationOverlayViewports: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.resyncAnnotationOverlayViewports), /* harmony export */ retryWithBackoff: () => (/* reexport safe */ _lib_pipes_exponential_backoff_pipe__WEBPACK_IMPORTED_MODULE_35__.retryWithBackoff), /* harmony export */ rotateArray: () => (/* reexport safe */ _lib_arrays__WEBPACK_IMPORTED_MODULE_4__.rotateArray), /* harmony export */ sCurvePointOnPath: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.sCurvePointOnPath), /* harmony export */ saveScreenshots: () => (/* reexport safe */ _lib_browser_save_screenshots__WEBPACK_IMPORTED_MODULE_6__.saveScreenshots), /* harmony export */ scurveTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.scurveTypes), /* harmony export */ separatePhases: () => (/* reexport safe */ _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__.separatePhases), /* harmony export */ setShaderCallback: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.setShaderCallback), /* harmony export */ setShaderReplacement: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.setShaderReplacement), /* harmony export */ setVascularGpuMaskMode: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.setVascularGpuMaskMode), /* harmony export */ setVascularGpuMaskOutlierOpacity: () => (/* reexport safe */ _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__.setVascularGpuMaskOutlierOpacity), /* harmony export */ setViewportLightsToHeadlight: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.setViewportLightsToHeadlight), /* harmony export */ signedDistanceToPlane: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.signedDistanceToPlane), /* harmony export */ silenceAnnotationOverlays: () => (/* reexport safe */ _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__.silenceAnnotationOverlays), /* harmony export */ silhouetteContainsClick: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.silhouetteContainsClick), /* harmony export */ slabAxesForViewport: () => (/* reexport safe */ _lib_cornerstone_viewport_rays__WEBPACK_IMPORTED_MODULE_49__.slabAxesForViewport), /* harmony export */ snapPositionToAngle: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.snapPositionToAngle), /* harmony export */ snapPositionToLine: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.snapPositionToLine), /* harmony export */ snapPositionToSpline: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.snapPositionToSpline), /* harmony export */ splineTypes: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.splineTypes), /* harmony export */ stripsToPolys: () => (/* reexport safe */ _lib_vtk_strips_to_polys__WEBPACK_IMPORTED_MODULE_54__.stripsToPolys), /* harmony export */ svgIconsPerToolType: () => (/* reexport safe */ _lib_constants__WEBPACK_IMPORTED_MODULE_13__.svgIconsPerToolType), /* harmony export */ swapToStandardVolumeMapper: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.swapToStandardVolumeMapper), /* harmony export */ throttle: () => (/* reexport safe */ _lib_throttle_debounce__WEBPACK_IMPORTED_MODULE_32__.throttle), /* harmony export */ throttleTrailing: () => (/* reexport safe */ _lib_throttle_debounce__WEBPACK_IMPORTED_MODULE_32__.throttleTrailing), /* harmony export */ toCamelCase: () => (/* reexport safe */ _lib_camel_case__WEBPACK_IMPORTED_MODULE_8__.toCamelCase), /* harmony export */ toDicomDate: () => (/* reexport safe */ _lib_dicom_format_dicom_date_helper__WEBPACK_IMPORTED_MODULE_62__.toDicomDate), /* harmony export */ toFiniteNumber: () => (/* reexport safe */ _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__.toFiniteNumber), /* harmony export */ transformRayToLocal: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.transformRayToLocal), /* harmony export */ translate: () => (/* reexport safe */ _lib_translate_handler__WEBPACK_IMPORTED_MODULE_33__.translate), /* harmony export */ validateCtModality: () => (/* reexport safe */ _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__.validateCtModality), /* harmony export */ validateInstances: () => (/* reexport safe */ _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__.validateInstances), /* harmony export */ validateViewportAngle: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.validateViewportAngle), /* harmony export */ vec3ToPosition: () => (/* reexport safe */ _lib_position__WEBPACK_IMPORTED_MODULE_27__.vec3ToPosition), /* harmony export */ vectorToAngulation: () => (/* reexport safe */ _lib_geometry__WEBPACK_IMPORTED_MODULE_18__.vectorToAngulation), /* harmony export */ vertexReplacement: () => (/* reexport safe */ _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__.vertexReplacement), /* harmony export */ waitAsync: () => (/* reexport safe */ _lib_promises__WEBPACK_IMPORTED_MODULE_28__.waitAsync), /* harmony export */ waitForVolumeActorLoad: () => (/* reexport safe */ _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__.waitForVolumeActorLoad), /* harmony export */ withShell: () => (/* reexport safe */ _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__.withShell), /* harmony export */ withTimeout: () => (/* reexport safe */ _lib_promises__WEBPACK_IMPORTED_MODULE_28__.withTimeout), /* harmony export */ worldToIndex: () => (/* reexport safe */ _lib_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_44__.worldToIndex), /* harmony export */ wrapAngle: () => (/* reexport safe */ _lib_angles__WEBPACK_IMPORTED_MODULE_0__.wrapAngle) /* harmony export */ }); /* harmony import */ var _lib_angles__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/angles */ 13413); /* harmony import */ var _lib_angulation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/angulation */ 88583); /* harmony import */ var _lib_annotation_structure_names__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/annotation-structure-names */ 78733); /* harmony import */ var _lib_chamber_structure_names__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/chamber-structure-names */ 50806); /* harmony import */ var _lib_arrays__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/arrays */ 75079); /* harmony import */ var _lib_browser_keyboard_targets__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/browser/keyboard-targets */ 82034); /* harmony import */ var _lib_browser_save_screenshots__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/browser/save-screenshots */ 67605); /* harmony import */ var _lib_backend_api_url__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./lib/backend-api-url */ 30836); /* harmony import */ var _lib_camel_case__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./lib/camel-case */ 68568); /* harmony import */ var _lib_clamp_range__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./lib/clamp-range */ 19414); /* harmony import */ var _lib_click_info__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./lib/click-info */ 98318); /* harmony import */ var _lib_cn__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./lib/cn */ 89912); /* harmony import */ var _lib_colors__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./lib/colors */ 24217); /* harmony import */ var _lib_constants__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./lib/constants */ 11280); /* harmony import */ var _lib_drag_bounds__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./lib/drag-bounds */ 20165); /* harmony import */ var _lib_export_json__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./lib/export-json */ 49618); /* harmony import */ var _lib_format_export_filename__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./lib/format-export-filename */ 66255); /* harmony import */ var _lib_generate_unique_name__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./lib/generate-unique-name */ 73442); /* harmony import */ var _lib_geometry__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./lib/geometry */ 63134); /* harmony import */ var _lib_import_json__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./lib/import-json */ 84503); /* harmony import */ var _lib_increment_name__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./lib/increment-name */ 66222); /* harmony import */ var _lib_interpolation__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./lib/interpolation */ 28235); /* harmony import */ var _lib_matrix__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./lib/matrix */ 46084); /* harmony import */ var _lib_memoization__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./lib/memoization */ 83775); /* harmony import */ var _lib_multiphase__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./lib/multiphase */ 71717); /* harmony import */ var _lib_object3d_geometry__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./lib/object3d-geometry */ 60786); /* harmony import */ var _lib_pick_file_from_disk__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./lib/pick-file-from-disk */ 22344); /* harmony import */ var _lib_position__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./lib/position */ 60174); /* harmony import */ var _lib_promises__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./lib/promises */ 75379); /* harmony import */ var _lib_range__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./lib/range */ 12896); /* harmony import */ var _lib_signals__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./lib/signals */ 84736); /* harmony import */ var _lib_svg__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./lib/svg */ 1331); /* harmony import */ var _lib_throttle_debounce__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./lib/throttle-debounce */ 30245); /* harmony import */ var _lib_translate_handler__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./lib/translate-handler */ 35498); /* harmony import */ var _lib_is_equal_set__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./lib/is-equal-set */ 95349); /* harmony import */ var _lib_pipes_exponential_backoff_pipe__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./lib/pipes/exponential-backoff.pipe */ 4251); /* harmony import */ var _lib_pipes_dicom_date_pipe__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./lib/pipes/dicom-date.pipe */ 10272); /* harmony import */ var _lib_pipes_dicom_person_name_pipe__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./lib/pipes/dicom-person-name.pipe */ 61971); /* harmony import */ var _lib_pipes_or_dash_pipe__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./lib/pipes/or-dash.pipe */ 261); /* harmony import */ var _lib_injection_tokens_env_injection_token__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./lib/injection-tokens/env-injection-token */ 42035); /* harmony import */ var _lib_injection_tokens_is_dev_build_injection_token__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./lib/injection-tokens/is-dev-build-injection-token */ 13253); /* harmony import */ var _lib_cornerstone_cornerstone_init_service__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./lib/cornerstone/cornerstone-init.service */ 66236); /* harmony import */ var _lib_cornerstone_cornerstone_tool_group__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./lib/cornerstone/cornerstone-tool-group */ 55871); /* harmony import */ var _lib_cornerstone_cornerstone_helpers__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./lib/cornerstone/cornerstone-helpers */ 20530); /* harmony import */ var _lib_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./lib/cornerstone/cornerstone-volume */ 25489); /* harmony import */ var _lib_cornerstone_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./lib/cornerstone/vascular-mask-gpu */ 85199); /* harmony import */ var _lib_cornerstone_annotation_overlay__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./lib/cornerstone/annotation-overlay */ 11114); /* harmony import */ var _lib_cornerstone_viewport_types__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./lib/cornerstone/viewport-types */ 63420); /* harmony import */ var _lib_cornerstone_viewport_widgets__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./lib/cornerstone/viewport-widgets */ 86880); /* harmony import */ var _lib_cornerstone_viewport_rays__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./lib/cornerstone/viewport-rays */ 408); /* harmony import */ var _lib_cornerstone_hardware_selector__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./lib/cornerstone/hardware-selector */ 78214); /* harmony import */ var _lib_segmentation_region_growing__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./lib/segmentation/region-growing */ 1554); /* harmony import */ var _lib_vtk_mappers__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./lib/vtk/mappers */ 60579); /* harmony import */ var _lib_vtk_shaders__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ./lib/vtk/shaders */ 2951); /* harmony import */ var _lib_vtk_strips_to_polys__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ./lib/vtk/strips-to-polys */ 85444); /* harmony import */ var _lib_webgl_program__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ./lib/webgl/program */ 77931); /* harmony import */ var _lib_dicom_dicom_image_loader_token__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./lib/dicom/dicom-image-loader.token */ 14007); /* harmony import */ var _lib_dicom_extract_dicom10__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ./lib/dicom/extract-dicom10 */ 67227); /* harmony import */ var _lib_dicom_extract_window_metadata__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ./lib/dicom/extract-window-metadata */ 1712); /* harmony import */ var _lib_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ./lib/dicom/windowing-presets */ 21423); /* harmony import */ var _lib_dicom_extract_pixel_data__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ./lib/dicom/extract-pixel-data */ 92627); /* harmony import */ var _lib_dicom_parse_dicom_date_helper__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./lib/dicom/parse-dicom-date.helper */ 32495); /* harmony import */ var _lib_dicom_format_dicom_date_helper__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ./lib/dicom/format-dicom-date.helper */ 50277); /* harmony import */ var _lib_dicom_dicom_instances_validation__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ./lib/dicom/dicom-instances-validation */ 77983); /* harmony import */ var _lib_dicom_normalize_series_uid__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ./lib/dicom/normalize-series-uid */ 18116); /* harmony import */ var _lib_volume_viewer_default_viewport_config__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! ./lib/volume-viewer/default-viewport-config */ 30050); /* harmony import */ var _lib_volume_viewer_build_series_window_state__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(/*! ./lib/volume-viewer/build-series-window-state */ 29324); /* harmony import */ var _lib_volume_viewer_map_viewport_to_orientation__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(/*! ./lib/volume-viewer/map-viewport-to-orientation */ 3009); /* harmony import */ var _lib_volume_viewer_camera_interpolation__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(/*! ./lib/volume-viewer/camera-interpolation */ 34417); /* harmony import */ var _lib_geometry_calculate_coronal_angle__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(/*! ./lib/geometry/calculate-coronal-angle */ 14445); /* harmony import */ var _lib_geometry_convex_hull__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(/*! ./lib/geometry/convex-hull */ 16147); /* harmony import */ var _lib_geometry_octree__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(/*! ./lib/geometry/octree */ 90702); /* harmony import */ var _lib_debug__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(/*! ./lib/debug */ 46401); // Rxjs Pipes // Injection Tokens // Cornerstone // VTK.js // WebGL // Dicom Parser // Volume viewer // Geometry // Debug /***/ }, /***/ 13413 /*!**************************************!*\ !*** ./libs/utils/src/lib/angles.ts ***! \**************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ deg2rad: () => (/* binding */ deg2rad), /* harmony export */ rad2deg: () => (/* binding */ rad2deg), /* harmony export */ wrapAngle: () => (/* binding */ wrapAngle) /* harmony export */ }); const DEG2RAD = Math.PI / 180; function deg2rad(degrees) { return degrees * DEG2RAD; } const RAD2DEG = 180 / Math.PI; function rad2deg(radians) { return radians * RAD2DEG; } function wrapAngle(angle, range = 360) { return (angle % range + range) % range; } /***/ }, /***/ 88583 /*!******************************************!*\ !*** ./libs/utils/src/lib/angulation.ts ***! \******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ formatAngulation: () => (/* binding */ formatAngulation), /* harmony export */ formatAngulationtxt: () => (/* binding */ formatAngulationtxt), /* harmony export */ formatCaudCran: () => (/* binding */ formatCaudCran), /* harmony export */ formatRaoLao: () => (/* binding */ formatRaoLao) /* harmony export */ }); function formatAngulationtxt(angulation, isPosterior) { return formatRaoLao(Math.round(angulation.rl)).direction + ' ' + formatRaoLao(Math.round(angulation.rl)).formattedValue + ' ' + formatCaudCran(Math.round(angulation.cc)).direction + ' ' + formatCaudCran(Math.round(angulation.cc)).formattedValue; } function formatRaoLao(number_) { if (number_ === 0) { return { direction: 'R/L', formattedValue: '0°', value: 0 }; } const absValue = Math.abs(number_); const formatted = absValue.toFixed(1).replace('.0', '') + '°'; return { direction: number_ < 0 ? 'RAO' : 'LAO', formattedValue: formatted, value: absValue }; } function formatCaudCran(number_) { if (number_ === 0) { return { direction: 'C/C', formattedValue: '0°', value: 0 }; } const absValue = Math.abs(number_); const formatted = absValue.toFixed(1).replace('.0', '') + '°'; return { direction: number_ < 0 ? 'CAUD' : 'CRAN', formattedValue: formatted, value: absValue }; } function formatAngulation(angulation, isPosterior) { const raoLao = formatRaoLao(Math.round(angulation.rl)); const caudCran = formatCaudCran(Math.round(angulation.cc)); return { caudCran, isPosterior, raoLao }; } /***/ }, /***/ 78733 /*!**********************************************************!*\ !*** ./libs/utils/src/lib/annotation-structure-names.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ANNOTATION_STRUCTURE_NAMES: () => (/* binding */ ANNOTATION_STRUCTURE_NAMES) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /** * Suggested structure names offered when renaming an annotation, grouped by measurement * type so the rename autocomplete can narrow the list to what's clinically relevant for * that annotation. Types not listed here (e.g. 3D objects) get no suggestions — renaming * stays free text only. */ const ANNOTATION_STRUCTURE_NAMES = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE]: ['Aortic annular plane angulation (for coplanar/cusp-overlap projection prediction)', 'Aorto-mitral angle', 'LVOT-to-aortic-root (septal) angle', 'Cusp / sinus angles', 'Access-vessel take-off angle', 'Access-vessel tortuosity angle', 'Catheter/delivery trajectory angle'], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE]: ['Aortic annulus', 'LVOT', 'Sinotubular junction', 'Sinus of Valsalva cross-section', 'Ascending aorta cross-section', 'Mitral annulus', 'Tricuspid annulus', 'Neo-LVOT cross-section', 'LAA ostium', 'LAA landing-zone', 'Pulmonary valve annulus', 'Vessel minimal-luminal-area cross-section', 'Septal defect', 'Interatrial septum'], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE]: ['Aortic annulus maximum diameter', 'Aortic annulus minimum diameter', 'Left coronary height', 'Right coronary height', 'Sinus of Valsalva diameter', 'Sinotubular junction diameter', 'Ascending aorta diameter', 'LVOT diameter', 'Membranous septum length', 'Mitral septal–lateral (AP) diameter', 'Intercommissural (CC) diameter', 'Trigone-to-trigone distance', 'Aorto-mitral / neo-LVOT dimension', 'LAA ostium diameter', 'LAA ostium landing-zone diameter', 'LAA ostium depth', 'ASD defect diameter', 'VSD defect diameter', 'PFO tunnel length', 'Superior ASD rim length', 'Anterior ASD rim length', 'Inferior ASD rim length', 'Posterior ASD rim length', 'Minimal luminal diameter'], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE]: ['Aortic centerline', 'Iliofemoral arterial centerline', 'Axillary/subclavian arterial centerline', 'Carotid arterial centerline', 'LVOT-to-aorta centerline', 'Aortic leaflet length', 'Aortic arch curvature', 'Delivery-system path'], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT]: ['Left coronary ostium', 'Right coronary ostium', 'Left coronary cusp nadir', 'Right coronary cusp nadir', 'Non-coronary cusp nadir', 'Aortic commissure LCC–RCC', 'Aortic commissure RCC–NCC', 'Aortic commissure NCC–LCC', 'Right mitral fibrous trigones', 'Left mitral fibrous trigones', 'Mitral valve commissure (medial)', 'Mitral valve commissure (lateral)', 'LV apex', 'Membranous septum superior reference point', 'Papillary muscle head'] }; /***/ }, /***/ 75079 /*!**************************************!*\ !*** ./libs/utils/src/lib/arrays.ts ***! \**************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ rotateArray: () => (/* binding */ rotateArray) /* harmony export */ }); function rotateArray(array, step = 1) { const index = (step % array.length + array.length) % array.length; return [...array.slice(-index), ...array.slice(0, -index)]; } /***/ }, /***/ 30836 /*!***********************************************!*\ !*** ./libs/utils/src/lib/backend-api-url.ts ***! \***********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isValidBackendApiUrl: () => (/* binding */ isValidBackendApiUrl), /* harmony export */ normalizeBackendApiUrl: () => (/* binding */ normalizeBackendApiUrl) /* harmony export */ }); const BACKEND_API_PATH = '/api'; function normalizeBackendApiUrl(apiUrl) { return apiUrl.trim().replaceAll(/\/$/g, ''); } function isValidBackendApiUrl(apiUrl) { const normalized = normalizeBackendApiUrl(apiUrl); try { const parsed = new URL(normalized); const validProtocol = parsed.protocol === 'http:' || parsed.protocol === 'https:'; const validPath = parsed.pathname.replaceAll(/\/$/g, '').endsWith(BACKEND_API_PATH); return validProtocol && validPath && !parsed.search && !parsed.hash; } catch { return false; } } /***/ }, /***/ 82034 /*!********************************************************!*\ !*** ./libs/utils/src/lib/browser/keyboard-targets.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isEditableTarget: () => (/* binding */ isEditableTarget), /* harmony export */ isInteractiveTarget: () => (/* binding */ isInteractiveTarget) /* harmony export */ }); /** * Returns true when the target accepts text or typeahead input. */ function isEditableTarget(target) { if (!(target instanceof HTMLElement)) return false; return Boolean(target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.tagName === 'SELECT' || target.isContentEditable); } /** * Returns true for targets that can accept text or typeahead input OR elements the keyboard activates directly. */ function isInteractiveTarget(target) { if (!(target instanceof HTMLElement)) return false; return isEditableTarget(target) || target.tagName === 'BUTTON' || target.tagName === 'A'; } /***/ }, /***/ 67605 /*!********************************************************!*\ !*** ./libs/utils/src/lib/browser/save-screenshots.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ saveScreenshots: () => (/* binding */ saveScreenshots) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jszip */ 34999); /* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jszip__WEBPACK_IMPORTED_MODULE_1__); function saveScreenshots(_x) { return _saveScreenshots.apply(this, arguments); } function _saveScreenshots() { _saveScreenshots = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* ({ document, outputFileName, selectors }) { const zip = new (jszip__WEBPACK_IMPORTED_MODULE_1___default())(); for (const selector of selectors) { const element = document.querySelector(selector); if (!element) { continue; } const canvas = element instanceof HTMLCanvasElement ? element : element.querySelector('canvas'); if (!(canvas instanceof HTMLCanvasElement)) { continue; } const imageBlob = yield canvasToBlob(canvas); if (!imageBlob) { continue; } const baseName = selector.startsWith('#') ? selector.slice(1) : selector; const safeName = baseName.replaceAll(/[^a-zA-Z0-9_-]/g, '-') // Replace invalid chars with dash .replaceAll(/((-+))/g, '-') // Replace multiple dashes with single dash .replaceAll(/(^-|-$)/g, '') || // Remove leading/trailing dashes 'screenshot'; zip.file(`${safeName}.png`, imageBlob); } if (Object.keys(zip.files).length === 0) { return; } const zipBlob = yield zip.generateAsync({ type: 'blob' }); downloadBlob(document, zipBlob, outputFileName); }); return _saveScreenshots.apply(this, arguments); } function canvasToBlob(canvas) { return new Promise(resolve => { canvas.toBlob(blob => resolve(blob ?? undefined), 'image/png'); }); } function downloadBlob(document, blob, filename) { const link = document.createElement('a'); const objectUrl = URL.createObjectURL(blob); link.href = objectUrl; link.download = filename; document.body.append(link); link.click(); link.remove(); URL.revokeObjectURL(objectUrl); } /***/ }, /***/ 68568 /*!******************************************!*\ !*** ./libs/utils/src/lib/camel-case.ts ***! \******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ toCamelCase: () => (/* binding */ toCamelCase) /* harmony export */ }); function toCamelCase(label) { // Split the string by common separators (space, hyphen, underscore) // and map each word to the correct case, then join them. return label.split(/[-_\s]+/).map((word, index) => { if (index === 0) { return word.toLowerCase(); } return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(''); } /***/ }, /***/ 50806 /*!*******************************************************!*\ !*** ./libs/utils/src/lib/chamber-structure-names.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CHAMBER_STRUCTURE_NAMES: () => (/* binding */ CHAMBER_STRUCTURE_NAMES) /* harmony export */ }); const CHAMBER_STRUCTURE_NAMES = ['1-chamber R', '1-chamber L', '2-chamber R', '2-chamber L', '3-chamber R', '3-chamber L', '4-chamber R', '4-chamber L', 'Mitral valve en-face', 'Aortic valve en-face', 'Tricuspid valve en-face', 'Pulmonic valve enface', 'Left atrial appendage en-face', 'Bi-caval']; /***/ }, /***/ 19414 /*!*******************************************!*\ !*** ./libs/utils/src/lib/clamp-range.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ clampRange: () => (/* binding */ clampRange) /* harmony export */ }); /** Clamp to [min, max], if the range is inverted (min > max), pin to min. */ function clampRange(value, min, max) { if (min > max) return min; return Math.min(Math.max(value, min), max); } /***/ }, /***/ 98318 /*!******************************************!*\ !*** ./libs/utils/src/lib/click-info.ts ***! \******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ clickInfo: () => (/* binding */ clickInfo), /* harmony export */ isDoubleClick: () => (/* binding */ isDoubleClick) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 93067); /** * Generate a ClickInfo record from a MouseEvent. */ function clickInfo(event) { return { position: [event.offsetX, event.offsetY], time: event.timeStamp }; } /** * Check if two clicks happened close enough to each other in time and distance to be considered a double-click. */ function isDoubleClick(a, b, thresholds) { const { distance = 10, time = 250 } = thresholds ?? {}; if (Math.abs(a.time - b.time) > time) return false; if (gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(a.position, b.position) > distance) return false; return true; } /***/ }, /***/ 89912 /*!**********************************!*\ !*** ./libs/utils/src/lib/cn.ts ***! \**********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cn: () => (/* binding */ cn) /* harmony export */ }); /* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! clsx */ 29309); /* harmony import */ var tailwind_merge__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tailwind-merge */ 72649); function cn(...inputs) { return (0,tailwind_merge__WEBPACK_IMPORTED_MODULE_1__.twMerge)((0,clsx__WEBPACK_IMPORTED_MODULE_0__.clsx)(inputs)); } /***/ }, /***/ 24217 /*!**************************************!*\ !*** ./libs/utils/src/lib/colors.ts ***! \**************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cssVariableToNormalizedRgb: () => (/* binding */ cssVariableToNormalizedRgb), /* harmony export */ hexToNormalizedRgb: () => (/* binding */ hexToNormalizedRgb), /* harmony export */ parseHexColor: () => (/* binding */ parseHexColor), /* harmony export */ randomColor: () => (/* binding */ randomColor) /* harmony export */ }); function parseHexColor(hex) { // Remove the '#' if present const cleanHex = hex.startsWith('#') ? hex.slice(1) : hex; // Check for valid hex string length (e.g., FFF or FFFFFF) if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex)) { console.error(`Invalid hex color format: '${hex}'`); return; } let r, g, b; if (cleanHex.length === 3) { // Handle shorthand hex (e.g., #F00) const [hexR, hexG, hexB] = cleanHex; if (!hexR || !hexG || !hexB) return; r = Number.parseInt(hexR + hexR, 16); g = Number.parseInt(hexG + hexG, 16); b = Number.parseInt(hexB + hexB, 16); } else { // Handle full hex (e.g., #FF0000) r = Number.parseInt(cleanHex.slice(0, 2), 16); g = Number.parseInt(cleanHex.slice(2, 4), 16); b = Number.parseInt(cleanHex.slice(4, 6), 16); } return { b, g, r }; } /** * Hex color to a [r, g, b] triple normalized to 0..1, the format Cornerstone * and VTK expect. Falls back to black on invalid input. */ function hexToNormalizedRgb(hex) { const rgb = parseHexColor(hex); return rgb ? [rgb.r / 255, rgb.g / 255, rgb.b / 255] : [0, 0, 0]; } /** * Resolved value of an emitted design-token CSS variable as a normalized * [r, g, b] triple for Cornerstone and VTK. Reads at call time so the PrimeNG * preset has emitted the variables by then. Supports hex-valued tokens only. * A missing variable or a non-hex value (color-mix, rgb) falls back to black * with a console warning. For libraries that cannot depend on @tomoverse/ui * (for example data-access, which ui depends on). */ function cssVariableToNormalizedRgb(name) { const value = globalThis.getComputedStyle(globalThis.document.documentElement).getPropertyValue(name).trim(); const rgb = value ? parseHexColor(value) : undefined; if (!rgb) { console.warn(`cssVariableToNormalizedRgb: '${name}' resolved to '${value}', using black.`); return [0, 0, 0]; } return [rgb.r / 255, rgb.g / 255, rgb.b / 255]; } function randomColor() { // eslint-disable-next-line sonarjs/pseudo-random const randomColor = Math.floor(Math.random() * 16_777_215); let hexColor = randomColor.toString(16); while (hexColor.length < 6) { hexColor = '0' + hexColor; } return '#' + hexColor; } /***/ }, /***/ 11280 /*!*****************************************!*\ !*** ./libs/utils/src/lib/constants.ts ***! \*****************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ANALYSIS_BASE_NAME: () => (/* binding */ ANALYSIS_BASE_NAME), /* harmony export */ ANNOTATION_NAME_MAX_LENGTH: () => (/* binding */ ANNOTATION_NAME_MAX_LENGTH), /* harmony export */ CHAMBER_NAME_MAX_LENGTH: () => (/* binding */ CHAMBER_NAME_MAX_LENGTH), /* harmony export */ DEFAULT_CROSSHAIR_SIZE: () => (/* binding */ DEFAULT_CROSSHAIR_SIZE), /* harmony export */ DEFAULT_PRESET_NAME: () => (/* binding */ DEFAULT_PRESET_NAME), /* harmony export */ DEFAULT_SAMPLE_DISTANCE_MULTIPLIER: () => (/* binding */ DEFAULT_SAMPLE_DISTANCE_MULTIPLIER), /* harmony export */ DEFAULT_VIEWPORT_CONFIG: () => (/* binding */ DEFAULT_VIEWPORT_CONFIG), /* harmony export */ DEFAULT_VOLUME_RENDERING_PRESET: () => (/* binding */ DEFAULT_VOLUME_RENDERING_PRESET), /* harmony export */ DEFAULT_WINDOW_PRESET: () => (/* binding */ DEFAULT_WINDOW_PRESET), /* harmony export */ DICOM_IMPORTER_TABLE_COLUMN_CONFIG: () => (/* binding */ DICOM_IMPORTER_TABLE_COLUMN_CONFIG), /* harmony export */ INIT_CAMERA_MATRIX: () => (/* binding */ INIT_CAMERA_MATRIX), /* harmony export */ LOW_SAMPLE_DISTANCE_MULTIPLIER: () => (/* binding */ LOW_SAMPLE_DISTANCE_MULTIPLIER), /* harmony export */ MAX_RECENT_WORK_SESSIONS: () => (/* binding */ MAX_RECENT_WORK_SESSIONS), /* harmony export */ VOLUME_RENDERING_PRESETS: () => (/* binding */ VOLUME_RENDERING_PRESETS), /* harmony export */ WORK_SESSION_CREATED_STATE_KEY: () => (/* binding */ WORK_SESSION_CREATED_STATE_KEY), /* harmony export */ WORK_SESSION_NEW_KEY: () => (/* binding */ WORK_SESSION_NEW_KEY), /* harmony export */ allScurveTypes: () => (/* binding */ allScurveTypes), /* harmony export */ allSplineTypes: () => (/* binding */ allSplineTypes), /* harmony export */ angleTypes: () => (/* binding */ angleTypes), /* harmony export */ attachedProjectionCurve: () => (/* binding */ attachedProjectionCurve), /* harmony export */ automatedTypes: () => (/* binding */ automatedTypes), /* harmony export */ closedSpline: () => (/* binding */ closedSpline), /* harmony export */ colorNotEditableTypes: () => (/* binding */ colorNotEditableTypes), /* harmony export */ defaultRxdbConfig: () => (/* binding */ defaultRxdbConfig), /* harmony export */ distanceTypes: () => (/* binding */ distanceTypes), /* harmony export */ modelTypes: () => (/* binding */ modelTypes), /* harmony export */ nameNotEditableTypes: () => (/* binding */ nameNotEditableTypes), /* harmony export */ namesForToolTypes: () => (/* binding */ namesForToolTypes), /* harmony export */ noVisibilityTypes: () => (/* binding */ noVisibilityTypes), /* harmony export */ notDeletableTypes: () => (/* binding */ notDeletableTypes), /* harmony export */ planeTypes: () => (/* binding */ planeTypes), /* harmony export */ pointTypes: () => (/* binding */ pointTypes), /* harmony export */ projectionCurveAngle: () => (/* binding */ projectionCurveAngle), /* harmony export */ projectionCurveIntersection: () => (/* binding */ projectionCurveIntersection), /* harmony export */ relativeTypes: () => (/* binding */ relativeTypes), /* harmony export */ scurveTypes: () => (/* binding */ scurveTypes), /* harmony export */ splineTypes: () => (/* binding */ splineTypes), /* harmony export */ svgIconsPerToolType: () => (/* binding */ svgIconsPerToolType) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const distanceTypes = ['Distance', 'Distance XYZ', 'Attached distance XYZ', 'Attached distance', 'Chord', 'Closest distance', 'Projected distance', 'Closest distance to one tool', 'Projected distance to one tool', 'Center distance to one tool']; const closedSpline = ['Closed spline']; const splineTypes = ['Attached spline', 'Open spline']; const allSplineTypes = [...splineTypes, ...closedSpline]; const angleTypes = ['Angle', 'Angle between splines', 'Angle between spline axes']; const pointTypes = ['Point', 'Attached point', 'Planar point', 'Curvature point']; const RCAHeight = 'RCA height'; const minDiameter = 'Min diameter'; const maxDiameter = 'Max diameter'; const projectionCurveIntersection = 'Projection curve intersection'; const projectionCurveAngle = 'Projection curve angle'; const attachedProjectionCurve = 'Attached projection curve'; const scurveTypes = [attachedProjectionCurve, 'Projection curve from 1 view', 'Projection curve from 2 views']; const allScurveTypes = [...scurveTypes, projectionCurveIntersection, projectionCurveAngle, attachedProjectionCurve]; const modelTypes = ['Model']; const planeTypes = [...splineTypes, ...angleTypes, ...modelTypes]; const noVisibilityTypes = ['Projection curve angle']; const automatedTypes = ['Closest distance', 'Projected distance']; const nameNotEditableTypes = [attachedProjectionCurve]; const colorNotEditableTypes = [attachedProjectionCurve]; const notDeletableTypes = [attachedProjectionCurve]; const relativeTypes = { 'Angle between splines': [closedSpline, closedSpline], 'Attached distance': [[distanceTypes, splineTypes, pointTypes].flat()], 'Attached distance XYZ': [[distanceTypes, splineTypes, pointTypes].flat()], 'Attached point': [[distanceTypes, splineTypes].flat()], 'Attached spline': [['Open spline']], Chord: [splineTypes], 'Closest distance': [[distanceTypes, splineTypes, pointTypes].flat(), [distanceTypes, splineTypes, pointTypes].flat()], 'Curvature point': [splineTypes].flat(), 'Planar point': [[...closedSpline, 'Attached spline']], 'Projected distance': [closedSpline, pointTypes] }; const namesForToolTypes = { Angle: ['Aorto-mitral angle'], 'Angle between splines': ['Aorto-mitral angle'], 'Attached distance': [RCAHeight, 'LM height', maxDiameter, minDiameter], 'Attached distance XYZ': [RCAHeight, 'LM height', maxDiameter, minDiameter], 'Attached point': ['Cusp nadir'], 'Attached spline': ['Bifurcation'], Chord: [RCAHeight, 'LM height', maxDiameter, minDiameter], 'Closed spline': ['Aortic valve annulus', 'Mitral valve annulus', 'Tricuspid valve annulus', 'Pulmonic valve annulus', 'LAA orifice'], 'Closest distance': [RCAHeight, 'LM height', maxDiameter, minDiameter], Distance: [RCAHeight, 'LM height', maxDiameter, minDiameter], 'Distance XYZ': [RCAHeight, 'LM height', maxDiameter, minDiameter], Model: [], 'Open spline': ['Aorta centerline', 'Right common iliac centerline', 'Left external iliac centerline', 'Right external iliac centerline', 'Left external iliac centerline', 'Left common femoral centerline', 'Left common femoral centerline', 'LM centerline', 'LAD centerline', 'LCx centerline', 'RCA centerline'], 'Planar point': ['Cusp nadir'], Point: ['Papillary muscle head', 'RCA ostium', 'LM ostium'], 'Projected distance': [RCAHeight, 'LM height', maxDiameter, minDiameter] }; const svgIconsPerToolType = [[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.ANGLE, angleTypes], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.OPEN_SPLINE, splineTypes], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.CLOSED_SPLINE, closedSpline], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.DISTANCE, distanceTypes], [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.AnnotationSourceType.POINT, pointTypes], ['cube', modelTypes], ['s-curve', scurveTypes], [['s-curve-point', projectionCurveIntersection]], ['s-curve-angle', [projectionCurveAngle]], [['Region'], 'region']]; const DICOM_IMPORTER_TABLE_COLUMN_CONFIG = [{ field: 'patientName', header: 'Patient name' }, { field: 'id', header: 'ID' }, { field: 'studyDate', header: 'Study date' }, { field: 'modality', header: 'Modality' }, { field: 'series', header: 'Series' }, { field: 'images', header: 'Images' }, { field: 'studyDesc', header: 'Study description' }, { field: 'desc', header: 'Description' }, { field: 'gating', header: 'Gating' }]; const INIT_CAMERA_MATRIX = [0, 1, 0, 1, 0, 0, 0, 0, -1]; const DEFAULT_VOLUME_RENDERING_PRESET = _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.FLUOROSCOPIC; const DEFAULT_SAMPLE_DISTANCE_MULTIPLIER = 15; const LOW_SAMPLE_DISTANCE_MULTIPLIER = 50; const DEFAULT_VIEWPORT_CONFIG = { type: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.ViewportType.ORTHOGRAPHIC }; const DEFAULT_PRESET_NAME = 'Default'; const DEFAULT_WINDOW_PRESET = { level: 0, name: 'Custom', width: 1400 }; const WORK_SESSION_NEW_KEY = 'new'; const ANALYSIS_BASE_NAME = 'Analysis'; /** * Router navigation state flag set by the create flow when it redirects the * `new` route to the real session uid. The route reuse strategy keeps the * viewer component alive only for navigations carrying this flag. */ const WORK_SESSION_CREATED_STATE_KEY = 'workSessionCreated'; /** Maximum number of recently opened work sessions shown as tabs in the top navigation. */ const MAX_RECENT_WORK_SESSIONS = 3; const VOLUME_RENDERING_PRESETS = { [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO]: { airTissueThreshold: -287, ambient: 0.28, bloodCalciumThreshold: 667, diffuse: 0.75, distalDepth: -100, imageQuality: 50, label: 'Endovascular', opacityTransitionWidth: 170, proximalDepth: 0, rgbTransitionWidth: 56, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.ENDO, specular: 0.23, specularPower: 38, tissueBloodThreshold: 140 }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.FLUOROSCOPIC]: { brightness: -0.3, distalDepth: -36, imageQuality: 50, label: 'Fluoroscopic', proximalDepth: 40, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.FLUOROSCOPIC, threshold: 132 }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.MIP]: { // brightness/threshold here are window level/width (see MipSettings) - MIP just projects // the highest HU along each ray, so it displays like any other CT image. Start from the // same window/level default MPR views use rather than a MIP-specific guess. brightness: DEFAULT_WINDOW_PRESET.level, distalDepth: -36, imageQuality: 50, label: 'MIP', proximalDepth: 40, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.MIP, threshold: DEFAULT_WINDOW_PRESET.width }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR]: { ambient: 0.27, bloodCalciumThreshold: 588, clusterSize: 10_000, diffuse: 0.84, // Persisted sessions are clamped to these bounds by work-session migration v18. distalDepth: -75, erosionRadius: 2, gridStep: 15, hasAcceptedSegmentation: false, imageQuality: 50, label: 'Vascular', maxHU: 1000, minHU: 170, opacityTransitionWidth: 1, outlierOpacity: 0, proximalDepth: 75, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.VASCULAR, specular: 0.4, specularPower: 20, tissueBloodThreshold: 215, vascularSegmentationState: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VascularSegmentationState.NONE, vascularThresholdsAutoTuned: false }, [_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.XRAY]: { brightness: -0.3, distalDepth: -66, imageQuality: 50, label: 'X-Ray', proximalDepth: 58, selectedPreset: _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.VolumeRenderingOption.XRAY, threshold: 240 } }; const defaultRxdbConfig = { devMode: false, name: 'tomoverse_db' }; const DEFAULT_CROSSHAIR_SIZE = 3; const ANNOTATION_NAME_MAX_LENGTH = 60; const CHAMBER_NAME_MAX_LENGTH = 60; /***/ }, /***/ 11114 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/annotation-overlay.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ addAnnotationActor: () => (/* binding */ addAnnotationActor), /* harmony export */ addAnnotationGhostActor: () => (/* binding */ addAnnotationGhostActor), /* harmony export */ detachAnnotationOverlay: () => (/* binding */ detachAnnotationOverlay), /* harmony export */ getAnnotationActor: () => (/* binding */ getAnnotationActor), /* harmony export */ getAnnotationActors: () => (/* binding */ getAnnotationActors), /* harmony export */ getAnnotationOverlayRenderer: () => (/* binding */ getAnnotationOverlayRenderer), /* harmony export */ initAnnotationOverlay: () => (/* binding */ initAnnotationOverlay), /* harmony export */ removeAnnotationActor: () => (/* binding */ removeAnnotationActor), /* harmony export */ removeAnnotationGhostActor: () => (/* binding */ removeAnnotationGhostActor), /* harmony export */ resetAnnotationOverlaysForTest: () => (/* binding */ resetAnnotationOverlaysForTest), /* harmony export */ resyncAnnotationOverlayViewports: () => (/* binding */ resyncAnnotationOverlayViewports), /* harmony export */ silenceAnnotationOverlays: () => (/* binding */ silenceAnnotationOverlays) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Renderer */ 45471); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _viewport_widgets__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./viewport-widgets */ 86880); // Per-viewport overlay `vtkRenderer` at layer 1, registered on the viewport // as a widget so Cornerstone's per-pass `getWidgetRenderers()` toggles its // draw flag. VR is the exception — annotations route to the primary // renderer so they z-test against the volume's pre-pass depth. const WIDGET_ID = 'tomoverse:annotation-overlay'; const overlays = new Map(); function syncOverlayFromPrimary(overlay, primary) { if (!primary) return; const rect = primary.getViewport?.(); if (rect) { overlay.setViewport(...rect); } const camera = primary.getActiveCamera?.(); if (camera && overlay.getActiveCamera?.() !== camera) { overlay.setActiveCamera(camera); } } function attachRenderer(viewport) { const primary = viewport.getRenderer?.(); const renderWindow = primary?.getRenderWindow?.(); if (!primary || !renderWindow) return undefined; const camera = primary.getActiveCamera?.(); if (!camera) return undefined; if ((renderWindow.getNumberOfLayers?.() ?? 1) < 2) { renderWindow.setNumberOfLayers?.(2); } const renderer = _kitware_vtk_js_Rendering_Core_Renderer__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); renderer.setActiveCamera(camera); renderWindow.addRenderer(renderer); renderer.setLayer(1); renderer.setPreserveColorBuffer(true); // vtkRenderer defaults to draw=true; flip it off so unguarded renders // (e.g. `vtkOffscreenMultiRenderWindow.resize()`) don't paint every // overlay at once before cornerstone's per-pass toggling takes over. renderer.setDraw(false); syncOverlayFromPrimary(renderer, primary); return renderer; } function registerWidget(viewport, record) { let enabled = true; const widget = { // Returning nothing short-circuits cornerstone's `removeWidgets` cleanup // path; we manage actors ourselves in `record.actors`. getActor() { return; }, getEnabled: () => enabled, getRenderer: () => { const renderer = record.renderer; if (!renderer) return; syncOverlayFromPrimary(renderer, viewport.getRenderer?.()); return renderer; }, setEnabled: value => { enabled = value; } }; viewport.addWidget(WIDGET_ID, widget); return widget; } function ensureRecord(viewport) { const existing = overlays.get(viewport.id); if (existing?.viewport && existing.viewport !== viewport) { detachAnnotationOverlay(existing.viewport); } let record = overlays.get(viewport.id); if (!record) { record = { actors: new Map() }; overlays.set(viewport.id, record); } // In VR the overlay is only attached on demand (when a ghost actor is // added) — primary annotation actors live on the primary renderer. if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.ViewportType.VOLUME_3D) return record; attachOverlayIfNeeded(viewport, record, /* reattachActors */true); return record; } function attachOverlayIfNeeded(viewport, record, reattachActors) { if (record.renderer || viewport.isDisabled) return; record.renderer = attachRenderer(viewport); if (!record.renderer) return; if (reattachActors) { for (const actor of record.actors.values()) { record.renderer.addActor(actor); } } const primary = viewport.getRenderer?.(); record.renderWindow = primary?.getRenderWindow?.() ?? undefined; record.widget = registerWidget(viewport, record); record.viewport = viewport; } function targetRenderer(viewport, record) { if (viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.ViewportType.VOLUME_3D) { return viewport.getRenderer?.(); } return record.renderer; } function addAnnotationActor(viewport, uid, actor) { if (viewport.isDisabled) return; const record = ensureRecord(viewport); const target = targetRenderer(viewport, record); const existing = record.actors.get(uid); if (existing && existing !== actor) { target?.removeActor(existing); } record.actors.set(uid, actor); target?.addActor(actor); } function removeAnnotationActor(viewport, uid) { const record = overlays.get(viewport.id); if (!record) return; const actor = record.actors.get(uid); if (!actor) return; record.actors.delete(uid); if (viewport.isDisabled) return; targetRenderer(viewport, record)?.removeActor(actor); } function addAnnotationGhostActor(viewport, uid, actor) { if (viewport.isDisabled) return; let record = overlays.get(viewport.id); if (!record) { record = { actors: new Map() }; overlays.set(viewport.id, record); } attachOverlayIfNeeded(viewport, record, /* reattachActors */false); if (!record.renderer) return; record.ghostActors ??= new Map(); const existing = record.ghostActors.get(uid); if (existing && existing !== actor) { record.renderer.removeActor(existing); } record.ghostActors.set(uid, actor); record.renderer.addActor(actor); } function removeAnnotationGhostActor(viewport, uid) { const record = overlays.get(viewport.id); if (!record?.ghostActors) return; const actor = record.ghostActors.get(uid); if (!actor) return; record.ghostActors.delete(uid); if (!viewport.isDisabled) { record.renderer?.removeActor(actor); } } function getAnnotationActor(viewportId, uid) { return overlays.get(viewportId)?.actors.get(uid); } function getAnnotationActors(viewportId) { const record = overlays.get(viewportId); if (!record) return []; return [...record.actors.values(), ...(record.ghostActors?.values() ?? [])]; } function getAnnotationOverlayRenderer(viewportId) { return overlays.get(viewportId)?.renderer; } /** Eagerly attaches the overlay renderer for a viewport at enable time so the * GL layer is present before any post-processing pass touches the render-window * state, avoiding GL save/restore conflicts on first annotation draw. * VOLUME_3D is included because ghost actors (annotation preview) lazily attach * the overlay on that viewport type too, and that lazy attach is what trips the * GL state when it happens mid-render after the post-process pipeline is live. */ function initAnnotationOverlay(viewport) { if (viewport.isDisabled) return; let record = overlays.get(viewport.id); if (!record) { record = { actors: new Map() }; overlays.set(viewport.id, record); } attachOverlayIfNeeded(viewport, record, /* reattachActors */true); } function resyncAnnotationOverlayViewports(viewports) { for (const viewport of viewports) { const record = overlays.get(viewport.id); if (!record?.renderer || viewport.isDisabled) continue; syncOverlayFromPrimary(record.renderer, viewport.getRenderer?.()); } } function silenceAnnotationOverlays() { for (const record of overlays.values()) { record.renderer?.setDraw(false); } } function resetAnnotationOverlaysForTest() { overlays.clear(); } function detachAnnotationOverlay(viewport) { const record = overlays.get(viewport.id); if (!record) return; if (record.viewport && record.viewport !== viewport) return; overlays.delete(viewport.id); (0,_viewport_widgets__WEBPACK_IMPORTED_MODULE_2__.removeViewportWidget)(viewport, WIDGET_ID); if (!viewport.isDisabled) { detachAnnotationActors(viewport, record); } const renderer = record.renderer; if (!renderer) return; record.renderWindow?.removeRenderer?.(renderer); renderer.delete?.(); } function detachAnnotationActors(viewport, record) { const isVolume3D = viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.ViewportType.VOLUME_3D; if (isVolume3D) { const primary = viewport.getRenderer?.(); for (const actor of record.actors.values()) { primary?.removeActor(actor); } } const overlay = record.renderer; if (!overlay) return; if (!isVolume3D) { for (const actor of record.actors.values()) { overlay.removeActor(actor); } } for (const actor of record.ghostActors?.values() ?? []) { overlay.removeActor(actor); } } /***/ }, /***/ 83283 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/cornerstone-core.token.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CORNERSTONE_CORE: () => (/* binding */ CORNERSTONE_CORE) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 10372); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 96035); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @cornerstonejs/core */ 17291); const CORNERSTONE_CORE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('CORNERSTONE_CORE', { factory: () => ({ cornerstoneStreamingImageVolumeLoader: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__.cornerstoneStreamingImageVolumeLoader, imageLoader: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__, metaData: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__, volumeLoader: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ }) }); /***/ }, /***/ 20530 /*!***************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/cornerstone-helpers.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CLIP_FACE_TARGET_LINE: () => (/* binding */ CLIP_FACE_TARGET_LINE), /* harmony export */ ENDO_KEY_LIGHT_ELEVATION: () => (/* binding */ ENDO_KEY_LIGHT_ELEVATION), /* harmony export */ FLUORO_ATTENUATION_PER_MM: () => (/* binding */ FLUORO_ATTENUATION_PER_MM), /* harmony export */ FLUORO_REF_MAX_HU: () => (/* binding */ FLUORO_REF_MAX_HU), /* harmony export */ FLUORO_REF_MIN_HU: () => (/* binding */ FLUORO_REF_MIN_HU), /* harmony export */ RADON_COLOR_TARGET_LINE: () => (/* binding */ RADON_COLOR_TARGET_LINE), /* harmony export */ TOMOVERSE_IMAGE_VOLUME_SCHEME: () => (/* reexport safe */ _tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_20__.TOMOVERSE_IMAGE_VOLUME_SCHEME), /* harmony export */ TRANSPARENT_SAMPLE_TARGET_LINE: () => (/* binding */ TRANSPARENT_SAMPLE_TARGET_LINE), /* harmony export */ TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE: () => (/* binding */ TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE), /* harmony export */ acceptVascularPreview: () => (/* binding */ acceptVascularPreview), /* harmony export */ addActorToViewport: () => (/* binding */ addActorToViewport), /* harmony export */ adjustProximalAndDistalClippingPlanes: () => (/* binding */ adjustProximalAndDistalClippingPlanes), /* harmony export */ applyAnnotationActorLighting: () => (/* binding */ applyAnnotationActorLighting), /* harmony export */ applyAnnotationLighting: () => (/* binding */ applyAnnotationLighting), /* harmony export */ applyEndoPresetToViewport: () => (/* binding */ applyEndoPresetToViewport), /* harmony export */ applyFluoroscopicPresetToViewport: () => (/* binding */ applyFluoroscopicPresetToViewport), /* harmony export */ applyImageSampleDistance: () => (/* binding */ applyImageSampleDistance), /* harmony export */ applyMipPresetToViewport: () => (/* binding */ applyMipPresetToViewport), /* harmony export */ applyVascularPresetToViewport: () => (/* binding */ applyVascularPresetToViewport), /* harmony export */ applyVascularRegionMask: () => (/* binding */ applyVascularRegionMask), /* harmony export */ applyVolume3dSampleDistance: () => (/* binding */ applyVolume3dSampleDistance), /* harmony export */ cancelVascularFullRun: () => (/* binding */ cancelVascularFullRun), /* harmony export */ computeAutoVascularThresholdsForVolume: () => (/* binding */ computeAutoVascularThresholdsForVolume), /* harmony export */ computeImageSampleDistance: () => (/* binding */ computeImageSampleDistance), /* harmony export */ computeVascularThresholdsFromMask: () => (/* binding */ computeVascularThresholdsFromMask), /* harmony export */ configureAnnotationActorLighting: () => (/* binding */ configureAnnotationActorLighting), /* harmony export */ decacheVolumeIds: () => (/* binding */ decacheVolumeIds), /* harmony export */ fluoroOpacityGain: () => (/* binding */ fluoroOpacityGain), /* harmony export */ getPrimaryImageVolume: () => (/* binding */ getPrimaryImageVolume), /* harmony export */ getVascularMaskLabels: () => (/* binding */ getVascularMaskLabels), /* harmony export */ getViewport: () => (/* binding */ getViewport), /* harmony export */ getVolumeActor: () => (/* reexport safe */ _volume_actor__WEBPACK_IMPORTED_MODULE_23__.getVolumeActor), /* harmony export */ getVolumeScalarRange: () => (/* binding */ getVolumeScalarRange), /* harmony export */ hasVolumeActor: () => (/* binding */ hasVolumeActor), /* harmony export */ installTransparentSampleEarlyOut: () => (/* binding */ installTransparentSampleEarlyOut), /* harmony export */ instantlyReapplyVascularMask: () => (/* binding */ instantlyReapplyVascularMask), /* harmony export */ isVtkVolumeMapper: () => (/* binding */ isVtkVolumeMapper), /* harmony export */ loadVolumeImages: () => (/* binding */ loadVolumeImages), /* harmony export */ previewVascularRegionMask: () => (/* binding */ previewVascularRegionMask), /* harmony export */ previewVascularRegionMaskLive: () => (/* binding */ previewVascularRegionMaskLive), /* harmony export */ raiseViewportKeyLight: () => (/* binding */ raiseViewportKeyLight), /* harmony export */ realScalarRangeByVolumeId: () => (/* binding */ realScalarRangeByVolumeId), /* harmony export */ releaseVascularWorkers: () => (/* reexport safe */ _segmentation_vascular_worker_helper__WEBPACK_IMPORTED_MODULE_13__.releaseVascularWorkers), /* harmony export */ restoreVascularForPresetSwitch: () => (/* binding */ restoreVascularForPresetSwitch), /* harmony export */ restoreVascularRegionMask: () => (/* binding */ restoreVascularRegionMask), /* harmony export */ restoreViewportLightsToCameraLight: () => (/* binding */ restoreViewportLightsToCameraLight), /* harmony export */ setViewportLightsToHeadlight: () => (/* binding */ setViewportLightsToHeadlight), /* harmony export */ swapToStandardVolumeMapper: () => (/* binding */ swapToStandardVolumeMapper), /* harmony export */ waitForVolumeActorLoad: () => (/* binding */ waitForVolumeActorLoad) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 59766); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 77569); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 38277); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @cornerstonejs/core */ 10372); /* harmony import */ var _kitware_vtk_js_Common_DataModel_Plane__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/Plane */ 68497); /* harmony import */ var _kitware_vtk_js_Rendering_Core_VolumeMapper_Constants__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/VolumeMapper/Constants */ 69041); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _angles__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../angles */ 13413); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../constants */ 11280); /* harmony import */ var _promises__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../promises */ 75379); /* harmony import */ var _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../segmentation/vascular-mask-compute */ 72024); /* harmony import */ var _segmentation_vascular_worker_helper__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../segmentation/vascular-worker-helper */ 31351); /* harmony import */ var _vtk_shaders__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../vtk/shaders */ 2951); /* harmony import */ var _annotation_overlay__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./annotation-overlay */ 11114); /* harmony import */ var _cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./cornerstone-volume */ 25489); /* harmony import */ var _osirix_clut__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./osirix-clut */ 16637); /* harmony import */ var _shaders_clip_face_frag_glsl__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./shaders/clip-face.frag.glsl */ 79448); /* harmony import */ var _shaders_two_sided_surface_lighting_frag_glsl__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./shaders/two-sided-surface-lighting.frag.glsl */ 11464); /* harmony import */ var _tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./tomoverse-volume-scheme */ 3389); /* harmony import */ var _vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./vascular-mask-gpu */ 85199); /* harmony import */ var _vasculardefault_osirix_clut__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./vasculardefault-osirix-clut */ 66174); /* harmony import */ var _volume_actor__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./volume-actor */ 68976); const ENDO_LIGHTING = _constants__WEBPACK_IMPORTED_MODULE_10__.VOLUME_RENDERING_PRESETS[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.VolumeRenderingOption.ENDO]; // Width of the fade-in/out ramp around each threshold boundary (in HU) const ENDO_TRANSPARENCY_WIDTH = 50; // Feature keys for the endo shader patches. const ENDO_CLIP_FACE_FEATURE = 'endo-clip-face'; const ENDO_SURFACE_LIGHTING_FEATURE = 'endo-surface-lighting'; // How much darkness 1mm of material at FLUORO_REF_MAX_HU adds. Higher = darker. // Range: 0.04-0.16. // - 0.04: you need ~100 mm blood column to reach black. That's the thickest thing in a cardiac scan. // So 0.04 is the floor: any lower and nothing is thick enough to ever reach black. // - 0.16: black is reached at ~20–25 mm(the size of an ordinary vessel). // Any higher and most structures above the threshold saturate to solid black, // you lose the thick-vs-thin shading that makes it read like an X-ray. const FLUORO_ATTENUATION_PER_MM = 0.16; // Fixed HU scale for the darkness slope, so the same HU darkens equally on every dataset. const FLUORO_REF_MIN_HU = -1024; const FLUORO_REF_MAX_HU = 3071; // Anchors are search keys for vtk's String.replace and must match // vtkVolumeFS.glsl byte-for-byte. They live as TS string literals (not // .glsl imports) so the GLSL pipeline can't rewrite their whitespace. // Exported so a test can verify each anchor still appears verbatim in // vtk.js's shipped vtkVolumeFS source. // Line from vtkVolumeFS.glsl COMPOSITE_BLEND, after the jitter-adjusted firstColor.a. const CLIP_FACE_TARGET_LINE = 'vec4 color = vec4(firstColor.rgb * firstColor.a, firstColor.a);'; // Two-sided-lighting block inside applySurfaceShadowLighting() in vtkVolumeFS.glsl. const TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE = `float ndotL = dot(normalVC.xyz, vertLightDirection); if (ndotL < 0.0 && twoSidedLighting == 1) { ndotL = -ndotL; } if (ndotL > 0.0) { // Diffuse diffuse += ndotL * attenuation * lights[ligthIdx].color; // Specular float vdotR = dot(-rayDirVC, normalize(vertLightDirection - 2.0 * ndotL * normalVC.xyz)); if (vdotR > 0.0)`; // Output line of the RADON_TRANSFORM_BLEND branch in vtkVolumeFS.glsl. // It appears exactly twice (thin-volume early-out and main path). const RADON_COLOR_TARGET_LINE = 'vec4(getColorFromTexture(normalizedRayIntensity, 0, 0.5), 1.0);'; // Normal-computation entry of getColorForDependentComponents() in vtkVolumeFS.glsl. const TRANSPARENT_SAMPLE_TARGET_LINE = 'vec4 normal0 = computeNormalForDensity(posIS, scalarInterp, 3);'; const TRANSPARENT_SAMPLE_FEATURE = 'transparent-sample-early-out'; // Hoists the shader's existing zero-opacity discard above the 6-fetch normal computation. // Unsound when opacity depends on the normal (gradient opacity), hence the guard. const transparentSampleEarlyOutFrag = ` #if vtkNumberOfComponents == 1 && !defined(EnabledGradientOpacity) if (getOpacityFromTexture(tValue.r, 0, 0.5) < EPSILON) { return vec4(0.0); } #endif vec4 normal0 = computeNormalForDensity(posIS, scalarInterp, 3); `; const FLUORO_RADON_COLOR_FEATURE = 'fluoro-radon-color'; const radonColorReplacement = colorInverted => colorInverted ? 'vec4(vec3(1.0 - clamp(normalizedRayIntensity, 0.0, 1.0)), 1.0);' : 'vec4(vec3(clamp(normalizedRayIntensity, 0.0, 1.0)), 1.0);'; const getViewport = (renderingEngineId, viewportId) => { const renderingEngine = (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__.getRenderingEngine)(renderingEngineId); if (!renderingEngine) { console.warn(`getViewport: no rendering engine ${renderingEngineId}`); return; } const viewport = renderingEngine.getViewport(viewportId); if (!viewport) { console.warn(`getViewport: no viewport ${viewportId} in engine ${renderingEngineId}`); return; } return viewport; }; function hasVolumeActor(viewport) { const actors = viewport.getActors(); const volumeEntry = actors.find(actorEntry => actorEntry.actor && actorEntry.referencedId && actorEntry.referencedId.startsWith(viewport.getVolumeId())); return !!volumeEntry?.actor; } function waitForVolumeActorLoad(_x) { return _waitForVolumeActorLoad.apply(this, arguments); } /** Theoretical range derived from DICOM bit-depth/rescale metadata - a dataset * stored wider than its actual content (e.g. bitsStored: 16 holding real * 0-4096 HU data) reports a far larger range than any voxel actually has. */ function _waitForVolumeActorLoad() { _waitForVolumeActorLoad = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (viewport) { while (!hasVolumeActor(viewport)) { yield (0,_promises__WEBPACK_IMPORTED_MODULE_11__.waitAsync)(10); } }); return _waitForVolumeActorLoad.apply(this, arguments); } function computeTheoreticalScalarRange(viewport) { const imageId = viewport.getImageIds()?.[0]; // Fall back to standard 12-bit signed CT range if no images are loaded if (!imageId) return [-1024, 3071]; const imagePixelModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__.get('imagePixelModule', imageId); const bitsStored = imagePixelModule?.bitsStored ?? 12; const maxRawValue = Math.pow(2, bitsStored) - 1; const modalityLut = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__.get('modalityLutModule', imageId); const rescaleSlope = modalityLut?.rescaleSlope ?? 1; const rescaleIntercept = modalityLut?.rescaleIntercept ?? -1024; // Theoretical range: min HU = intercept (raw=0), max HU = maxRaw * slope + intercept return [rescaleIntercept, maxRawValue * rescaleSlope + rescaleIntercept]; } /** volumeId -> observed [min, max] HU, computed once per loaded volume. * Exported so tests can reset it between cases that reuse the same volumeId. */ const realScalarRangeByVolumeId = new Map(); /** Scans every voxel once for its true observed HU range - the metadata-derived * theoretical range can hugely overstate this (see computeTheoreticalScalarRange). */ function computeRealScalarRange(volume) { const volumeData = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.exportFromImageVolume)(volume); if (!volumeData) return undefined; const { voxelData } = volumeData; let min = Infinity; let max = -Infinity; // eslint-disable-next-line unicorn/no-for-loop for (let index = 0; index < voxelData.length; index++) { const value = voxelData[index]; if (value < min) min = value; if (value > max) max = value; } return Number.isFinite(min) && Number.isFinite(max) ? [min, max] : undefined; } const getVolumeScalarRange = viewport => { if (!viewport) return [-1024, 3071]; const volumeId = viewport.getVolumeId(); const cached = volumeId ? realScalarRangeByVolumeId.get(volumeId) : undefined; if (cached) return cached; const volume = volumeId ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(volumeId) : undefined; const realRange = volume ? computeRealScalarRange(volume) : undefined; if (realRange) { if (volumeId) realScalarRangeByVolumeId.set(volumeId, realRange); return realRange; } // The volume's real voxel data isn't resolvable yet (e.g. still loading) - // fall back to the metadata-derived theoretical range for now. return computeTheoreticalScalarRange(viewport); }; const ANNOTATION_AMBIENT = 0.7; const ANNOTATION_DIFFUSE = 0.3; function applyAnnotationLighting(actor, viewport) { const property = actor.getProperty(); const lit = viewport.type === _tomoverse_enums__WEBPACK_IMPORTED_MODULE_8__.ViewportType.VOLUME_3D; property.setLighting(lit); if (lit) { property.setAmbient(ANNOTATION_AMBIENT); property.setDiffuse(ANNOTATION_DIFFUSE); } // VTK caches the shader based on the mapper's MTime. Property changes (setLighting, // setAmbient etc.) modify the property object but not the mapper, so the cached // shader may miss the new lighting settings on the first render. Bumping the mapper // forces a shader rebuild that picks up the correct lighting state immediately. actor.getMapper().modified?.(); } const configureAnnotationActorLighting = actor => { const property = actor.getProperty(); property.setAmbient?.(ENDO_LIGHTING.ambient); property.setDiffuse?.(ENDO_LIGHTING.diffuse); property.setSpecular?.(ENDO_LIGHTING.specular); property.setSpecularPower?.(ENDO_LIGHTING.specularPower); }; function applyAnnotationActorLighting(viewportId, renderMode) { const lightingEnabled = renderMode !== undefined; for (const actor of (0,_annotation_overlay__WEBPACK_IMPORTED_MODULE_15__.getAnnotationActors)(viewportId)) { const property = actor.getProperty?.(); if (!property) continue; property.setLighting(lightingEnabled); if (lightingEnabled) { configureAnnotationActorLighting(actor); } } } const applyEndoPresetToViewport = (viewport, airTissueThreshold, tissueBloodThreshold, bloodCalciumThreshold, render = true, lighting, opacityTransitionWidth = ENDO_TRANSPARENCY_WIDTH, rgbTransitionWidth = ENDO_TRANSPARENCY_WIDTH) => { const volumeActor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_23__.getVolumeActor)(viewport); if (!volumeActor) return; const volumeProperty = volumeActor.getProperty(); // Gradient opacity triggers a VTK shader rebuild that races our custom shader injection. volumeProperty.setUseGradientOpacity(0, false); const [minScalar, maxScalar] = getVolumeScalarRange(viewport); const W = rgbTransitionWidth; // Colors: #80273A (dark red / tissue), #F0DBA8 (light gold / blood), #FFFFFF (white / calcium) const rgb = volumeProperty.getRGBTransferFunction(0); rgb.removeAllPoints(); rgb.addRGBPoint(minScalar, 0, 0, 0); // air → black rgb.addRGBPoint(airTissueThreshold - W, 0, 0, 0); // black anchor rgb.addRGBPoint(airTissueThreshold - W + 1, 0.502, 0.153, 0.227); // → #80273A dark red rgb.addRGBPoint(tissueBloodThreshold, 0.941, 0.859, 0.659); // → #F0DBA8 light gold rgb.addRGBPoint(tissueBloodThreshold + W + 1, 0.941, 0.859, 0.659); // light gold anchor rgb.addRGBPoint(bloodCalciumThreshold - W, 1, 1, 1); // → #FFFFFF white rgb.addRGBPoint(maxScalar, 1, 1, 1); // white clamp rgb.modified(); const half = opacityTransitionWidth / 2; const opacity = volumeProperty.getScalarOpacity(0); opacity.removeAllPoints(); opacity.addPoint(minScalar, 0); opacity.addPoint(airTissueThreshold - half, 0); // air→tissue ramp start opacity.addPoint(airTissueThreshold + half, 1); // air→tissue ramp end opacity.addPoint(tissueBloodThreshold - half, 1); // tissue→blood ramp start opacity.addPoint(tissueBloodThreshold + half, 0); // tissue→blood ramp end opacity.addPoint(bloodCalciumThreshold - half, 0); // blood→calcium ramp start opacity.addPoint(bloodCalciumThreshold + half, 1); // blood→calcium ramp end opacity.addPoint(maxScalar, 1); opacity.modified(); volumeProperty.setShade(true); volumeProperty.setAmbient(lighting?.ambient ?? 0.25); volumeProperty.setDiffuse(lighting?.diffuse ?? 0.75); volumeProperty.setSpecular(lighting?.specular ?? 0.4); volumeProperty.setSpecularPower(lighting?.specularPower ?? 20); const mapper = volumeActor.getMapper(); if (mapper && isVtkVolumeMapper(mapper)) { mapper.setBlendMode(_kitware_vtk_js_Rendering_Core_VolumeMapper_Constants__WEBPACK_IMPORTED_MODULE_7__.BlendMode.COMPOSITE_BLEND); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.setShaderReplacement)(mapper, ENDO_CLIP_FACE_FEATURE, (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.fragmentReplacement)(CLIP_FACE_TARGET_LINE, _shaders_clip_face_frag_glsl__WEBPACK_IMPORTED_MODULE_18__["default"])); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.setShaderReplacement)(mapper, ENDO_SURFACE_LIGHTING_FEATURE, (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.fragmentReplacement)(TWO_SIDED_SURFACE_LIGHTING_TARGET_LINE, _shaders_two_sided_surface_lighting_frag_glsl__WEBPACK_IMPORTED_MODULE_19__["default"])); } viewport.getRenderer().setTwoSidedLighting(true); setViewportLightsToHeadlight(viewport); if (render) viewport.render(); }; const VASCULAR_TRANSPARENCY_WIDTH = 50; const VASCULAR_BLACK = [0, 0, 0]; const VASCULAR_WHITE = [1, 1, 1]; // applyVascularColorRamp multiplies the CLUT's own opacity stops by this value — the // CLUT already plateaus at ~0.97 (not 1) in its own y-values, so this stays an identity // multiplier rather than double-applying that dampening. const VASCULAR_PEAK_ALPHA = 1; const VASCULAR_DEFAULT_CLUT = (0,_osirix_clut__WEBPACK_IMPORTED_MODULE_17__.parseOsirixClut)(_vasculardefault_osirix_clut__WEBPACK_IMPORTED_MODULE_22__.VASCULARDEFAULT_OSIRIX_CLUT); /** The x-value of a CLUT curve stop, by index — throws instead of silently * remapping around a missing anchor. */ function requireClutStopX(stops, index) { const stop = stops[index]; if (!stop) throw new Error(`VASCULAR_DEFAULT_CLUT is missing curve stop ${index}`); return stop.x; } // Curve stops 1 (red) and 3 (cream) anchor the ramp to the caller's two thresholds. const VASCULAR_CLUT_TISSUE_BLOOD_ANCHOR_X = requireClutStopX(VASCULAR_DEFAULT_CLUT.colorStops, 1); const VASCULAR_CLUT_BLOOD_CALCIUM_ANCHOR_X = requireClutStopX(VASCULAR_DEFAULT_CLUT.colorStops, 3); // Last computed labels per volume — switching back to vascular mode // re-attaches instantly, no worker recompute. const vascularLabelCache = new WeakMap(); /** Shared worker invocation for the apply/preview/live paths. Returns * undefined if the computation was cancelled, superseded, or had no seeds. */ function computeVascularSegmentation(_x2, _x3, _x4, _x5, _x6, _x7, _x8) { return _computeVascularSegmentation.apply(this, arguments); } function _computeVascularSegmentation() { _computeVascularSegmentation = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (viewport, minHU, maxHU, seedWorldPos, gridStep, minClusterSize, erosionRadius, resolution = 'full') { const volumeId = viewport.getVolumeId(); const volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(volumeId); if (!volume) return undefined; let seedIJK; if (seedWorldPos) { const geometry = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.exportVolumeGeometry)(volume); if (!geometry) return undefined; const fractional = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.worldToIndex)(geometry, seedWorldPos); seedIJK = [Math.round(fractional[0]), Math.round(fractional[1]), Math.round(fractional[2])]; } // Isolated workers: a full run never blocks live ticks. A new full run // supersedes any in-flight one; the orchestrator coalesces previews. const kind = resolution === 'preview' ? 'preview' : 'full'; if (kind === 'full') (0,_segmentation_vascular_worker_helper__WEBPACK_IMPORTED_MODULE_13__.cancelPendingVascularRequests)('full'); const requestBase = { erosionRadius: erosionRadius ?? 0, gridStep, maxHU, minClusterSize: minClusterSize ?? 30_000, minHU, resolution, seedIJK, volumeKey: volumeId }; const response = yield requestVascularLabels(volume, volumeId, requestBase, kind); if (!response?.labelBuffer) return undefined; return { labels: new Uint8Array(response.labelBuffer), volume }; }); return _computeVascularSegmentation.apply(this, arguments); } function buildVascularVolumePayload(volume, kind) { const volumeData = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.exportFromImageVolume)(volume); if (!volumeData) return undefined; // Copy — postMessage neuters the sent buffer, which may alias the live // volume. The preview worker keeps only the downsampled copy. const workerInput = new Float32Array(volumeData.voxelData); return { payload: { dimensions: volumeData.dimensions, previewOnly: kind === 'preview' || undefined, voxelBuffer: workerInput.buffer }, transfer: [workerInput.buffer] }; } /** Sends the volume buffer only when the worker doesn't hold it resident; * one retry covers a worker that restarted since. Returns undefined when * superseded, cancelled, or the volume can't be exported. */ function requestVascularLabels(_x9, _x0, _x1, _x10) { return _requestVascularLabels.apply(this, arguments); } /** Caches then attaches the labels. Only exact (full-res) masks may be * accepted or silently instant-reapplied. */ function _requestVascularLabels() { _requestVascularLabels = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (volume, volumeKey, requestBase, kind) { let includeVolume = _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.workerVolumeKeys[kind] !== volumeKey; for (let attempt = 0; attempt < 2; attempt++) { let volumePayload = { payload: {}, transfer: [] }; if (includeVolume) { const built = buildVascularVolumePayload(volume, kind); if (!built) return undefined; volumePayload = built; } const requestId = _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.nextId++; _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.latestIds[kind] = requestId; let response; try { response = yield new Promise((resolve, reject) => { _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.pending.set(requestId, { kind, reject, resolve }); (0,_segmentation_vascular_worker_helper__WEBPACK_IMPORTED_MODULE_13__.getVascularWorker)(kind).postMessage({ ...requestBase, ...volumePayload.payload, requestId }, volumePayload.transfer); }); } catch { return undefined; } if (includeVolume) _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.workerVolumeKeys[kind] = volumeKey; if (requestId !== _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.vascularRequestState.latestIds[kind]) return undefined; if (!response.needsVolume) return response; includeVolume = true; } return undefined; }); return _requestVascularLabels.apply(this, arguments); } function attachComputedLabels(viewport, result, mode, exact) { vascularLabelCache.set(result.volume, { exact, labels: result.labels }); return (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.attachVascularGpuMask)(viewport, result.labels, mode, undefined, exact); } /** Resolves true once the worker's mask is attached in applied mode. */ function applyVascularRegionMask(_x11, _x12, _x13, _x14, _x15, _x16, _x17) { return _applyVascularRegionMask.apply(this, arguments); } /** Attaches the label mask in preview mode; acceptVascularPreview finalises * it, restoreVascularRegionMask discards it. */ function _applyVascularRegionMask() { _applyVascularRegionMask = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (viewport, minHU, maxHU, seedWorldPos, gridStep, minClusterSize, erosionRadius) { const result = yield computeVascularSegmentation(viewport, minHU, maxHU, seedWorldPos, gridStep, minClusterSize, erosionRadius); if (!result) return false; return attachComputedLabels(viewport, result, 'applied', true); }); return _applyVascularRegionMask.apply(this, arguments); } function previewVascularRegionMask(_x18, _x19, _x20, _x21, _x22, _x23, _x24) { return _previewVascularRegionMask.apply(this, arguments); } /** Rejects the in-flight exact run and terminates the full worker (the next * exact run resends the volume). The preview worker is untouched. */ function _previewVascularRegionMask() { _previewVascularRegionMask = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (viewport, minHU, maxHU, seedWorldPos, gridStep, minClusterSize, erosionRadius) { const result = yield computeVascularSegmentation(viewport, minHU, maxHU, seedWorldPos, gridStep, minClusterSize, erosionRadius); if (!result) return false; return attachComputedLabels(viewport, result, 'preview', true); }); return _previewVascularRegionMask.apply(this, arguments); } function cancelVascularFullRun() { (0,_segmentation_vascular_worker_helper__WEBPACK_IMPORTED_MODULE_13__.cancelPendingVascularRequests)('full'); } /** Low-res live preview for slider drags — approximate by design; the exact * slide-end run still goes through previewVascularRegionMask. */ function previewVascularRegionMaskLive(_x25, _x26) { return _previewVascularRegionMaskLive.apply(this, arguments); } /** Detaches the mask but keeps the label cache for an instant re-attach — * the other presets' shaders compile single-component. */ function _previewVascularRegionMaskLive() { _previewVascularRegionMaskLive = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (viewport, parameters) { const result = yield computeVascularSegmentation(viewport, parameters.minHU, parameters.maxHU, undefined, parameters.gridStep, parameters.clusterSize, parameters.erosionRadius, 'preview'); if (!result) return false; return attachComputedLabels(viewport, result, 'preview', false); }); return _previewVascularRegionMaskLive.apply(this, arguments); } function restoreVascularForPresetSwitch(viewport) { (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.detachVascularGpuMask)(viewport); } /** A shader-mode flip — no recompute or re-upload. Refuses a non-exact * (live preview) mask. */ function acceptVascularPreview(viewport) { if (!(0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.isVascularGpuMaskExact)(viewport)) return false; (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.setVascularGpuMaskMode)(viewport, 'applied'); return true; } /** Detaches the mask and drops the cached labels for the viewport's volume. */ function restoreVascularRegionMask(viewport) { (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.detachVascularGpuMask)(viewport); const volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(viewport.getVolumeId()); if (volume) vascularLabelCache.delete(volume); } /** Re-attaches the cached labels without re-running the worker, so returning * to vascular mode doesn't flash unmasked. Keeps the entry's exactness — * follow a non-exact reapply with a fresh exact run. */ function instantlyReapplyVascularMask(viewport, mode = 'applied') { const volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(viewport.getVolumeId()); if (!volume) return false; const cached = vascularLabelCache.get(volume); if (!cached) return false; return (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.attachVascularGpuMask)(viewport, cached.labels, mode, undefined, cached.exact); } /** The cached class-label array for a volume's vascular mask, if one has been computed. */ function getVascularMaskLabels(volume) { return vascularLabelCache.get(volume)?.labels; } /** Estimates (tissueBloodThreshold, bloodCalciumThreshold) from the volume's own HU * histogram — a per-scan starting point for the vascular color ramp. undefined when * voxel data isn't available or the histogram is too sparse/flat to trust. */ function computeAutoVascularThresholdsForVolume(volume) { const data = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.exportFromImageVolume)(volume); if (!data) return undefined; return (0,_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.computeAutoVascularThresholds)(data.voxelData); } /** Tightens (tissueBloodThreshold, bloodCalciumThreshold) to the 5th-95th percentile HU * of the accepted vessel mask's own voxels — a refinement once real segmentation exists. */ function computeVascularThresholdsFromMask(volume) { const labels = getVascularMaskLabels(volume); if (!labels) return undefined; const data = (0,_cornerstone_volume__WEBPACK_IMPORTED_MODULE_16__.exportFromImageVolume)(volume); if (!data) return undefined; const range = (0,_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.computePercentileRange)(data.voxelData, labels, _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_12__.VASCULAR_MASK_LABELS.vessel, 5, 95); if (!range) return undefined; return { bloodCalciumThreshold: range.high, tissueBloodThreshold: range.low }; } /** Builds the RGB ramp and opacity window from the reference OsiriX CLUT, remapped so * its own tissue/blood and blood/calcium anchor stops land on the caller's thresholds. */ function applyVascularColorRamp(property, tissueBloodThreshold, bloodCalciumThreshold, opacityValue, opacityTransitionWidth) { property.setUseGradientOpacity(0, false); const clut = (0,_osirix_clut__WEBPACK_IMPORTED_MODULE_17__.remapClutToThresholds)(VASCULAR_DEFAULT_CLUT, VASCULAR_CLUT_TISSUE_BLOOD_ANCHOR_X, VASCULAR_CLUT_BLOOD_CALCIUM_ANCHOR_X, tissueBloodThreshold, bloodCalciumThreshold); const rgb = property.getRGBTransferFunction(0); rgb.removeAllPoints(); for (const stop of clut.colorStops) rgb.addRGBPoint(stop.x, stop.r, stop.g, stop.b); rgb.modified(); // Alpha follows the CLUT's own curve up to bloodCalciumThreshold, then // falls to 0 so the outlier band (added separately) takes over cleanly. const half = opacityTransitionWidth / 2; const opacity = property.getScalarOpacity(0); opacity.removeAllPoints(); for (const stop of clut.opacityStops) { if (stop.x > bloodCalciumThreshold) continue; opacity.addPoint(stop.x, stop.opacity * opacityValue); } opacity.addPoint(bloodCalciumThreshold + half, 0); opacity.modified(); } /** Applies the vascular color ramp and shading parameters to a volume actor. Does not install a surface-lighting shader — uses VTK default gradient shading to avoid edge-glow artifacts at the CT volume boundary. */ function configureVascularVolumeActor(actor, tissueBloodThreshold, bloodCalciumThreshold, opacityValue, lighting, opacityTransitionWidth) { const property = actor.getProperty(); applyVascularColorRamp(property, tissueBloodThreshold, bloodCalciumThreshold, opacityValue, opacityTransitionWidth); property.setShade(true); property.setAmbient(lighting?.ambient ?? 0.25); property.setDiffuse(lighting?.diffuse ?? 0.75); property.setSpecular(lighting?.specular ?? 0.4); property.setSpecularPower(lighting?.specularPower ?? 20); const mapper = actor.getMapper(); if (mapper && isVtkVolumeMapper(mapper)) { mapper.setBlendMode(_kitware_vtk_js_Rendering_Core_VolumeMapper_Constants__WEBPACK_IMPORTED_MODULE_7__.BlendMode.COMPOSITE_BLEND); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_CLIP_FACE_FEATURE); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_SURFACE_LIGHTING_FEATURE); } } /** Configures the 3D viewport with the vascular transfer function, extending the TF to cover the outlier band and setting headlight. */ const applyVascularPresetToViewport = (viewport, tissueBloodThreshold, bloodCalciumThreshold, outlierOpacity = 0, render = true, lighting, opacityTransitionWidth = VASCULAR_TRANSPARENCY_WIDTH) => { const volumeActor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_23__.getVolumeActor)(viewport); if (!volumeActor) return; const [minScalar, maxScalar] = getVolumeScalarRange(viewport); configureVascularVolumeActor(volumeActor, tissueBloodThreshold, bloodCalciumThreshold, VASCULAR_PEAK_ALPHA, lighting, opacityTransitionWidth); // Above the calcium threshold, high-HU voxels render at outlierOpacity // pre-mask; the masked presentation lives in the mask shader's TF, not here. const property = volumeActor.getProperty(); const rgb = property.getRGBTransferFunction(0); rgb.addRGBPoint(minScalar, ...VASCULAR_BLACK); rgb.addRGBPoint(maxScalar, ...VASCULAR_WHITE); rgb.modified(); const half = opacityTransitionWidth / 2; // Keeps the high-HU band's rise clear of the blood ramp's fade-out. const HIGH_HU_BAND_GAP = 25; const opacity = property.getScalarOpacity(0); opacity.addPoint(minScalar, 0); opacity.addPoint(bloodCalciumThreshold + half + HIGH_HU_BAND_GAP, outlierOpacity); opacity.addPoint(maxScalar, outlierOpacity); opacity.modified(); // No-op unless a mask is attached — keeps the outlier-opacity slider live while masked. (0,_vascular_mask_gpu__WEBPACK_IMPORTED_MODULE_21__.setVascularGpuMaskOutlierOpacity)(viewport, outlierOpacity); setViewportLightsToHeadlight(viewport); if (render) viewport.render(); }; /** Maps the brightness slider [-1, 1.5] to the fluoro attenuation gain [0, 1.25]. */ const fluoroOpacityGain = brightness => Math.max(0, 0.5 + brightness * 0.5); /** Attenuation function for the Radon (DRR) projection. */ const applyFluoroAttenuationRamp = (volumeProperty, threshold, brightness, minScalar, maxScalar) => { const scalarOpacity = volumeProperty.getScalarOpacity(0); scalarOpacity.removeAllPoints(); const gain = fluoroOpacityGain(brightness); const mu = hu => gain * FLUORO_ATTENUATION_PER_MM * ((hu - FLUORO_REF_MIN_HU) / (FLUORO_REF_MAX_HU - FLUORO_REF_MIN_HU)); // Lowest HU in the dataset: zero darkening scalarOpacity.addPoint(minScalar, 0); if (threshold >= maxScalar) { // Threshold above the data range: nothing attenuates, volume is invisible scalarOpacity.addPoint(maxScalar, 0); } else { // Everything up to the threshold stays fully transparent scalarOpacity.addPoint(threshold, 0); // Jump to the slope right above the threshold, so the cutoff is sharp instead of a slow fade-in if (threshold + 1 < maxScalar) scalarOpacity.addPoint(threshold + 1, mu(threshold + 1)); // Linear slope up to the highest HU in the dataset: the denser the tissue, the darker it renders scalarOpacity.addPoint(maxScalar, mu(maxScalar)); } scalarOpacity.modified(); }; const applyFluoroscopicPresetToViewport = (viewport, selectedPreset, colorInverted = false, threshold = 0, brightness = 0, render = true) => { viewport.setProperties({ invert: false, preset: selectedPreset }); const volumeActor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_23__.getVolumeActor)(viewport); if (volumeActor) { const volumeProperty = volumeActor.getProperty(); const rgbTransferFunction = volumeProperty.getRGBTransferFunction(0); const [minScalar, maxScalar] = getVolumeScalarRange(viewport); // Under RADON_TRANSFORM_BLEND the color TF maps the accumulated ray // transmittance [0..1] to display grey (not HU!) rgbTransferFunction.removeAllPoints(); if (colorInverted) { // X-ray: dark background, attenuating structures brighten rgbTransferFunction.addRGBPoint(0, 1, 1, 1); rgbTransferFunction.addRGBPoint(1, 0, 0, 0); } else { // Fluoro: white background, attenuating structures darken rgbTransferFunction.addRGBPoint(0, 0, 0, 0); rgbTransferFunction.addRGBPoint(1, 1, 1, 1); } rgbTransferFunction.modified(); applyFluoroAttenuationRamp(volumeProperty, threshold, brightness, minScalar, maxScalar); const mapper = volumeActor.getMapper(); if (mapper && isVtkVolumeMapper(mapper)) { (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_CLIP_FACE_FEATURE); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_SURFACE_LIGHTING_FEATURE); const replacement = radonColorReplacement(colorInverted); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.setShaderReplacement)(mapper, FLUORO_RADON_COLOR_FEATURE, [(0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.fragmentReplacement)(RADON_COLOR_TARGET_LINE, replacement), (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.fragmentReplacement)(RADON_COLOR_TARGET_LINE, replacement)]); mapper.setBlendMode(_kitware_vtk_js_Rendering_Core_VolumeMapper_Constants__WEBPACK_IMPORTED_MODULE_7__.BlendMode.RADON_TRANSFORM_BLEND); } // Clear shading state left on the shared property by the endo preset volumeProperty.setShade(false); restoreViewportLightsToCameraLight(viewport); if (render) viewport.render(); } }; /** Configures the 3D viewport for Maximum Intensity Projection: VTK's native * BlendMode.MAXIMUM_INTENSITY_BLEND finds the single highest raw-HU sample along each ray and * colors/opacifies only that one winning sample - no compositing, no shading, and nothing left * for a threshold to decide (there's only ever one sample per ray, and it's always shown). The * result is a projected HU image, so it's displayed exactly like any other CT image: a window/ * level ramp over the real HU range, not the [0..1] transmittance domain the Radon presets * above use. Kept the same threshold/brightness parameter names fluoro/xray use (rather than * windowWidth/windowLevel) since they drive the same slider UI - here threshold is the window * width and brightness is the window level. */ const applyMipPresetToViewport = (viewport, selectedPreset, threshold, brightness, render = true) => { viewport.setProperties({ invert: false, preset: selectedPreset }); const volumeActor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_23__.getVolumeActor)(viewport); if (!volumeActor) return; const volumeProperty = volumeActor.getProperty(); const [minScalar, maxScalar] = getVolumeScalarRange(viewport); const windowWidth = threshold; const windowLevel = brightness; const rgbTransferFunction = volumeProperty.getRGBTransferFunction(0); rgbTransferFunction.removeAllPoints(); rgbTransferFunction.addRGBPoint(windowLevel - windowWidth / 2, 0, 0, 0); rgbTransferFunction.addRGBPoint(windowLevel + windowWidth / 2, 1, 1, 1); rgbTransferFunction.modified(); // MAXIMUM_INTENSITY_BLEND already picked the one winning sample per ray - opacity has // nothing left to decide, so keep it fully opaque across the data range. const scalarOpacity = volumeProperty.getScalarOpacity(0); scalarOpacity.removeAllPoints(); scalarOpacity.addPoint(minScalar, 1); scalarOpacity.addPoint(maxScalar, 1); scalarOpacity.modified(); const mapper = volumeActor.getMapper(); if (mapper && isVtkVolumeMapper(mapper)) { (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_CLIP_FACE_FEATURE); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, ENDO_SURFACE_LIGHTING_FEATURE); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.removeShaderReplacement)(mapper, FLUORO_RADON_COLOR_FEATURE); mapper.setBlendMode(_kitware_vtk_js_Rendering_Core_VolumeMapper_Constants__WEBPACK_IMPORTED_MODULE_7__.BlendMode.MAXIMUM_INTENSITY_BLEND); } // Clear shading state left on the shared property by the endo/vascular presets volumeProperty.setShade(false); restoreViewportLightsToCameraLight(viewport); if (render) viewport.render(); }; // Keep references to reusable clipping planes to avoid additional GC const proximalPlane = _kitware_vtk_js_Common_DataModel_Plane__WEBPACK_IMPORTED_MODULE_6__["default"].newInstance(); const distalPlane = _kitware_vtk_js_Common_DataModel_Plane__WEBPACK_IMPORTED_MODULE_6__["default"].newInstance(); const adjustProximalAndDistalClippingPlanes = (viewport, proximalDistance, distalDistance, render = true) => { const camera = viewport.getCamera(); const { focalPoint, viewPlaneNormal } = camera; if (!focalPoint || !viewPlaneNormal) { console.warn('adjustDistalClippingPlane3D: camera vectors undefined, skipping.'); return; } const volumeActors = viewport.getActors().filter(entry => { const mapper = entry.actor.getMapper?.(); return mapper ? isVtkVolumeMapper(mapper) : false; }).map(entry => entry.actor); if (volumeActors.length === 0) return; const proximalOrigin = [focalPoint[0] + viewPlaneNormal[0] * proximalDistance, focalPoint[1] + viewPlaneNormal[1] * proximalDistance, focalPoint[2] + viewPlaneNormal[2] * proximalDistance]; proximalPlane.setOrigin(proximalOrigin); //Adjust Proximal Clipping Plane const proximalNormal = [viewPlaneNormal[0] * -1, viewPlaneNormal[1] * -1, viewPlaneNormal[2] * -1]; proximalPlane.setNormal(proximalNormal); // Adjust Distal Clipping Plane const distalOrigin = [focalPoint[0] + viewPlaneNormal[0] * distalDistance, focalPoint[1] + viewPlaneNormal[1] * distalDistance, focalPoint[2] + viewPlaneNormal[2] * distalDistance]; distalPlane.setOrigin(distalOrigin); distalPlane.setNormal(viewPlaneNormal); // opposite orientation of proximal plane // Apply both planes to every volume actor (main + any outlier volumes) for (const actor of volumeActors) { const m = actor.getMapper(); if (!m || !isVtkVolumeMapper(m)) continue; m.removeAllClippingPlanes(); m.addClippingPlane(proximalPlane); m.addClippingPlane(distalPlane); } //set camera clipping range which is independent to a maximum value to avoid conflicts with other viewport states. const vtkCamera = viewport?.getRenderer().getActiveCamera(); vtkCamera.setClippingRange(-9999, 9999); if (render) viewport.render(); }; const isVtkVolumeMapper = mapper => { return !!mapper && 'setSampleDistance' in mapper; }; function setViewportLightsToHeadlight(viewport) { const renderer = viewport.getRenderer(); for (const light of renderer.getLights()) { light.setLightTypeToHeadLight(); } } function restoreViewportLightsToCameraLight(viewport) { const renderer = viewport.getRenderer(); for (const light of renderer.getLights()) { light.setLightTypeToCameraLight(); } } /** Degrees the endo key light is raised above the view axis, toward viewUp. */ const ENDO_KEY_LIGHT_ELEVATION = 30; /** * Re-aims the viewport lights from above the camera toward the focal point, * giving end-on anatomy directional shading an on-axis headlight cannot. * Must run after `updateLightsGeometryToFollowCamera`, which resets * headlights onto the view axis. */ function raiseViewportKeyLight(viewport, elevationDegrees = ENDO_KEY_LIGHT_ELEVATION) { const { focalPoint, position, viewUp } = viewport.getCamera(); if (!focalPoint || !position || !viewUp) return; const distance = Math.hypot(focalPoint[0] - position[0], focalPoint[1] - position[1], focalPoint[2] - position[2]); const upLength = Math.hypot(viewUp[0], viewUp[1], viewUp[2]); if (distance === 0 || upLength === 0) return; const offset = Math.tan((0,_angles__WEBPACK_IMPORTED_MODULE_9__.deg2rad)(elevationDegrees)) * distance / upLength; const renderer = viewport.getRenderer(); for (const light of renderer.getLights()) { light.setPosition(position[0] + viewUp[0] * offset, position[1] + viewUp[1] * offset, position[2] + viewUp[2] * offset); light.setFocalPoint(focalPoint[0], focalPoint[1], focalPoint[2]); } } function addActorToViewport(viewport, uid, actor) { if (viewport.isDisabled) return; // NOTE: `Viewport::addActor()` calls `updateCameraClippingPlanesAndRange()` internally, // which causes the volume actor to temporarily disappear. // Monkey-patching it like this is the best solution I've been able to find so far const original = viewport.updateCameraClippingPlanesAndRange.bind(viewport); viewport.updateCameraClippingPlanesAndRange = () => { // no-op }; viewport.addActor({ actor, uid }); viewport.updateCameraClippingPlanesAndRange = original; } /** First cached image volume, or undefined when none is loaded. */ function getPrimaryImageVolume() { return _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolumes().find(vol => vol.volumeId.startsWith(_tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_20__.TOMOVERSE_IMAGE_VOLUME_SCHEME)); } function loadVolumeImages(_x27) { return _loadVolumeImages.apply(this, arguments); } /** * Releases both volumes' voxel data (CPU + GPU) from Cornerstone's cache. Volumes aren't * counted toward cache's own size-based eviction the way images are, so nothing frees this * memory unless a caller explicitly does so - only call once no viewport is still bound to * either id (e.g. after switching every viewport to a different volume, or on teardown). * * Deliberately skips volume.destroy(): a still-in-flight image for this volume can still land * after this runs, and destroy() leaves that arrival crashing (visibly, repeatedly, for large * volumes) instead of a harmless no-op. cache.purgeCache() has the same restraint. */ function _loadVolumeImages() { _loadVolumeImages = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageIds, key = 'default') { // A per-phase key keeps each phase's volume distinct in the cache; without it, switching phases // would reuse (and re-render) the first phase's volume. const normalizedKey = key.replaceAll(/[^a-zA-Z0-9_.-]/g, '_'); const mprVolumeId = `${_tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_20__.TOMOVERSE_IMAGE_VOLUME_SCHEME}:volume-${normalizedKey}`; const volume3dId = `${_tomoverse_volume_scheme__WEBPACK_IMPORTED_MODULE_20__.TOMOVERSE_IMAGE_VOLUME_SCHEME}:volume-3d-${normalizedKey}`; yield Promise.all([loadVolume(mprVolumeId, imageIds), loadVolume(volume3dId, imageIds)]); return { mprVolumeId, volume3dId }; }); return _loadVolumeImages.apply(this, arguments); } function decacheVolumeIds(volumeIds) { for (const volumeId of [volumeIds.mprVolumeId, volumeIds.volume3dId]) { if (_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(volumeId)) { _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].removeVolumeLoadObject(volumeId); } } } // Maps the quality slider (0–100) to a vtkVolumeMapper imageSampleDistance. // factor=1 → full FBO; factor=4 → 1/4 size per dimension (1/16 total pixels, 4× faster). function computeImageSampleDistance(imageQuality) { return 1 + (1 - imageQuality / 100) * 3; } function loadVolume(_x28, _x29) { return _loadVolume.apply(this, arguments); } function _loadVolume() { _loadVolume = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (volumeId, imageIds) { let volume = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].getVolume(volumeId); if (!volume) { volume = yield _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__.createAndCacheVolume(volumeId, { imageIds }); } // Cornerstone has a race condition where if you call `volume.load()` // while it is currently loading, the callback will not fire. // However, if you call `volume.load()` once it is loaded, it will. // This is a temporary fix until we can restructure things to only require // a single `volume.load()` call. while (volume.loadStatus?.loading) { yield (0,_promises__WEBPACK_IMPORTED_MODULE_11__.waitAsync)(100); } yield new Promise(resolve => volume.load(() => resolve())); }); return _loadVolume.apply(this, arguments); } function swapToStandardVolumeMapper(actor) { const mapper = actor.getMapper(); if (mapper?.getClassName?.() !== 'vtkSharedVolumeMapper') return; actor.setMapper((0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.convertMapperToNotSharedMapper)(mapper)); } /** Keyed by its own feature so preset switches leave it installed; re-run after anything * that recreates mappers (viewport enable, phase switch). */ function installTransparentSampleEarlyOut(viewport) { for (const entry of viewport.getActors()) { const mapper = entry.actor.getMapper?.(); if (!mapper || !isVtkVolumeMapper(mapper)) continue; (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.setShaderReplacement)(mapper, TRANSPARENT_SAMPLE_FEATURE, (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_14__.fragmentReplacement)(TRANSPARENT_SAMPLE_TARGET_LINE, transparentSampleEarlyOutFrag, { replaceFirst: true })); } } // Voxels per ray step on the 3D viewport; Cornerstone's default is 0.5. const VOLUME_3D_SAMPLE_DISTANCE_VOXELS = 1; function applyVolume3dSampleDistance(viewport) { for (const entry of viewport.getActors()) { const mapper = entry.actor.getMapper?.(); if (!mapper || !isVtkVolumeMapper(mapper)) continue; const volumeMapper = mapper; const imageData = volumeMapper.getInputData(); const spacing = imageData?.getSpacing?.(); if (!spacing) continue; const averageSpacing = (spacing[0] + spacing[1] + spacing[2]) / 3; volumeMapper.setSampleDistance(averageSpacing * VOLUME_3D_SAMPLE_DISTANCE_VOXELS); } } // Sets the mapper's imageSampleDistance (FBO size divisor). // factor=1 → full resolution; factor>1 → reduced FBO (blurry but geometry-complete). // autoAdjustSampleDistances=false makes VTK's onAnimationFrameRateUpdate use imageSampleDistance // directly for _lastScale rather than adapting from frame rate. function applyImageSampleDistance(actor, factor) { const mapper = actor.getMapper(); if (!('setImageSampleDistance' in mapper)) return; mapper.setAutoAdjustSampleDistances(factor === 1); mapper.setImageSampleDistance(factor); } /***/ }, /***/ 66236 /*!********************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/cornerstone-init.service.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CornerstoneInitService: () => (/* binding */ CornerstoneInitService) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 15678); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/tools */ 16974); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 40072); class CornerstoneInitService { initialized = false; ensureInitialized() { var _this = this; return (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (_this.initialized) return; yield (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.init)({ debug: { statsOverlay: false }, rendering: { renderingEngineMode: 'contextPool' } }); yield _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_2__.init(); _this.initialized = true; })(); } static ɵfac = function CornerstoneInitService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CornerstoneInitService)(); }; static ɵprov = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"]({ token: CornerstoneInitService, factory: CornerstoneInitService.ɵfac, providedIn: 'root' }); } /***/ }, /***/ 55871 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/cornerstone-tool-group.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ addAndActivateToolsToGroup: () => (/* binding */ addAndActivateToolsToGroup), /* harmony export */ getOrRegisterNewToolGroup: () => (/* binding */ getOrRegisterNewToolGroup), /* harmony export */ registerCornerstoneTools: () => (/* binding */ registerCornerstoneTools), /* harmony export */ registerToolGroupForViewports: () => (/* binding */ registerToolGroupForViewports) /* harmony export */ }); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/tools */ 49541); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/tools */ 90125); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/tools */ 92792); /* harmony import */ var _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/tools */ 14904); const registerToolGroupForViewports = (toolGroupName, viewportIds, renderingEngineId, tool) => { const toolGroup = getOrRegisterNewToolGroup(toolGroupName); if (!toolGroup) { throw new Error(`Failed to create or get tool group`); } for (const viewportId of viewportIds) { toolGroup.addViewport(viewportId, renderingEngineId); } addAndActivateToolsToGroup(toolGroup, tool); return toolGroup; }; const addAndActivateToolsToGroup = (toolGroup, tools) => { if (Array.isArray(tools)) { for (const tool of tools) { addSingleToolToGroup(toolGroup, tool); } return; } addSingleToolToGroup(toolGroup, tools); }; const addSingleToolToGroup = (toolGroup, tool) => { if (!toolGroup.hasTool(tool.name)) { toolGroup.addTool(tool.name, tool.toolConfiguration); } toolGroup.setToolActive(tool.name, tool.toolBinding); }; const getOrRegisterNewToolGroup = toolGroupName => { return _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_2__["default"](toolGroupName) || _cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_3__["default"](toolGroupName); }; const registerCornerstoneTools = tools => { if (Array.isArray(tools)) { for (const tool of tools) { if (!_cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_1__.state.tools[tool.toolName]) { (0,_cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_0__.addTool)(tool); } } return; } if (!_cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_1__.state.tools[tools.toolName]) { (0,_cornerstonejs_tools__WEBPACK_IMPORTED_MODULE_0__.addTool)(tools); } }; /***/ }, /***/ 25489 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/cornerstone-volume.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ exportFromImageVolume: () => (/* binding */ exportFromImageVolume), /* harmony export */ exportVolumeGeometry: () => (/* binding */ exportVolumeGeometry), /* harmony export */ getAtIJK: () => (/* binding */ getAtIJK), /* harmony export */ worldToIndex: () => (/* binding */ worldToIndex) /* harmony export */ }); /** Geometry without the voxel data — getCompleteScalarDataArray may copy the * whole volume, so callers that only need coordinates use this instead. */ function exportVolumeGeometry(imageVolume) { const voxelManager = imageVolume.voxelManager; if (!voxelManager) return; return { dimensions: [...voxelManager.dimensions], direction: [...imageVolume.direction], origin: [...imageVolume.origin], spacing: [...imageVolume.spacing] }; } function getAtIJK({ dimensions, voxelData }, i, j, k) { const index = i + j * dimensions[0] + k * dimensions[0] * dimensions[1]; return voxelData[index] ?? 0; } function exportFromImageVolume(imageVolume) { const voxelManager = imageVolume.voxelManager; if (!voxelManager?.getCompleteScalarDataArray) return; return { dimensions: [...voxelManager.dimensions], direction: [...imageVolume.direction], origin: [...imageVolume.origin], spacing: [...imageVolume.spacing], voxelData: voxelManager.getCompleteScalarDataArray() }; } function worldToIndex({ direction, origin, spacing }, worldPos) { // Translate by origin const translated = [worldPos[0] - origin[0], worldPos[1] - origin[1], worldPos[2] - origin[2]]; // Apply inverse direction matrix (transpose since it's orthonormal) const invDir = transposeM3(direction); const rotated = multiplyM3V3(invDir, translated); // Divide by spacing return [rotated[0] / spacing[0], rotated[1] / spacing[1], rotated[2] / spacing[2]]; } function transposeM3(m) { return [m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]]; } function multiplyM3V3(m, v) { return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]]; } /***/ }, /***/ 78214 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/hardware-selector.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ findActorInArea: () => (/* binding */ findActorInArea), /* harmony export */ pickFromOverlay: () => (/* binding */ pickFromOverlay), /* harmony export */ pickFromVolume3DPrimary: () => (/* binding */ pickFromVolume3DPrimary) /* harmony export */ }); /* harmony import */ var _annotation_overlay__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./annotation-overlay */ 11114); // Hardware-selector picking helpers. Wrap VTK's selector pass so callers can // pick an actor under a screen pixel without owning the selector lifecycle. /** * A renderer only gets an OpenGL view node when the render window next traverses its * scene graph, so one added since the last render (a re-attached overlay, a viewport * re-enabled by a layout change) has none yet. vtk's `beginSelection` dereferences that * node without checking, and it throws *after* binding the selector's framebuffer and * before `endSelection` restores it - leaving it bound on the shared offscreen context, * where every later render draws into it instead of the canvas and each viewport copies * out the same stale image. */ function hasViewNode(view, renderer) { return Boolean(view.getViewNodeFor(renderer)); } /** Returns the actor under (cx, cy), expanding outward in a radius-square search. */ function findActorInArea(selector, cx, cy, radius) { const size = radius * 2 + 1; const offsets = Array.from({ length: size * size }, (_, index) => { const dx = index % size - radius; const dy = Math.floor(index / size) - radius; return { dist: dx * dx + dy * dy, dx, dy }; }); offsets.sort((a, b) => a.dist - b.dist); for (const { dx, dy } of offsets) { const pixInfo = selector.getPixelInformation([cx + dx, cy + dy], 0, []); if (pixInfo?.prop) return pixInfo.prop; } return undefined; } /** Hardware-pick from the annotation overlay renderer. */ function pickFromOverlay(viewportId, selector, view, vtkX, vtkY, radius) { const overlayRenderer = (0,_annotation_overlay__WEBPACK_IMPORTED_MODULE_0__.getAnnotationOverlayRenderer)(viewportId); if (!overlayRenderer) return undefined; if (!hasViewNode(view, overlayRenderer)) return undefined; overlayRenderer.setDraw(true); selector.setRenderer(overlayRenderer); if (!selector.captureBuffers()) return undefined; return findActorInArea(selector, vtkX, vtkY, radius); } /** Hardware-pick from a 3D viewport's primary renderer with the volume hidden, * so its fragment shader doesn't mask annotation pixels in transparent regions. */ function pickFromVolume3DPrimary(viewport, selector, view, vtkX, vtkY, radius) { const primary = viewport.getRenderer(); if (!hasViewNode(view, primary)) return undefined; const previousDraw = primary.getDraw?.() ?? false; primary.setDraw?.(true); const volumeId = viewport.getVolumeId(); const volumeActors = viewport.getActors().filter(entry => entry.referencedId?.startsWith(volumeId)).map(entry => entry.actor); const volumeVisibility = volumeActors.map(actor => actor.getVisibility()); for (const actor of volumeActors) actor.setVisibility(false); try { selector.setRenderer(primary); if (!selector.captureBuffers()) return undefined; return findActorInArea(selector, vtkX, vtkY, radius); } finally { for (const [index, actor] of volumeActors.entries()) { actor.setVisibility(volumeVisibility[index] ?? true); } primary.setDraw?.(previousDraw); } } /***/ }, /***/ 16637 /*!*******************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/osirix-clut.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ parseOsirixClut: () => (/* binding */ parseOsirixClut), /* harmony export */ remapClutToThresholds: () => (/* binding */ remapClutToThresholds) /* harmony export */ }); /** Support for CLUTs (color look-up tables) exported from OsiriX as a .plist and * checked in locally as JSON (see vasculardefault-osirix-clut.ts). */ /** Converts a raw OsiriX CLUT export into normalized control points, pairing each * color with the curve point at the same index (colors carry no x value of their * own). Throws if the two arrays don't line up 1:1. */ function parseOsirixClut(raw) { const colors = raw.colors[0] ?? []; const curve = raw.curves[0] ?? []; if (colors.length !== curve.length) { throw new Error(`OsiriX CLUT colors/curve length mismatch: ${colors.length} colors, ${curve.length} curve points.`); } const colorStops = colors.map((color, index) => { const point = curve[index]; if (!point) throw new Error(`OsiriX CLUT missing curve point ${index}`); return { b: color.blue, g: color.green, r: color.red, x: point.x }; }); const opacityStops = curve.map(point => ({ opacity: point.y, x: point.x })); return { colorStops, opacityStops }; } /** Affinely remaps a CLUT's x-axis so `referenceLowX`/`referenceHighX` land exactly on * `newLow`/`newHigh`, preserving the curve's shape while its core span tracks two * user-adjustable thresholds. */ function remapClutToThresholds(clut, referenceLowX, referenceHighX, newLow, newHigh) { // A zero/inverted target span can't map two distinct reference points onto two // distinct target points — fall back to a pure shift (scale 1) so the curve keeps // its shape/spacing instead of collapsing every stop onto a single x. const scale = newHigh > newLow ? (newHigh - newLow) / (referenceHighX - referenceLowX) : 1; const mapX = x => newLow + (x - referenceLowX) * scale; return { colorStops: clut.colorStops.map(stop => ({ ...stop, x: mapX(stop.x) })), opacityStops: clut.opacityStops.map(stop => ({ ...stop, x: mapX(stop.x) })) }; } /***/ }, /***/ 3389 /*!*******************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/tomoverse-volume-scheme.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TOMOVERSE_IMAGE_VOLUME_SCHEME: () => (/* binding */ TOMOVERSE_IMAGE_VOLUME_SCHEME) /* harmony export */ }); const TOMOVERSE_IMAGE_VOLUME_SCHEME = 'tomoverseImageVolume'; /***/ }, /***/ 85199 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/vascular-mask-gpu.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CUSTOM_COLOR_MIX_ANCHOR: () => (/* binding */ CUSTOM_COLOR_MIX_ANCHOR), /* harmony export */ VASCULAR_MASK_LABELS: () => (/* reexport safe */ _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS), /* harmony export */ attachVascularGpuMask: () => (/* binding */ attachVascularGpuMask), /* harmony export */ detachVascularGpuMask: () => (/* binding */ detachVascularGpuMask), /* harmony export */ isVascularGpuMaskAttached: () => (/* binding */ isVascularGpuMaskAttached), /* harmony export */ isVascularGpuMaskExact: () => (/* binding */ isVascularGpuMaskExact), /* harmony export */ setVascularGpuMaskMode: () => (/* binding */ setVascularGpuMaskMode), /* harmony export */ setVascularGpuMaskOutlierOpacity: () => (/* binding */ setVascularGpuMaskOutlierOpacity) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Common/Core/DataArray */ 40928); /* harmony import */ var _kitware_vtk_js_Common_DataModel_ImageData__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/ImageData */ 56394); /* harmony import */ var _kitware_vtk_js_Common_DataModel_PiecewiseFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @kitware/vtk.js/Common/DataModel/PiecewiseFunction */ 53173); /* harmony import */ var _kitware_vtk_js_Rendering_Core_ColorTransferFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/ColorTransferFunction */ 15722); /* harmony import */ var _kitware_vtk_js_Rendering_Core_VolumeProperty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/VolumeProperty */ 8043); /* harmony import */ var _kitware_vtk_js_Rendering_Core_VolumeProperty_Constants__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/VolumeProperty/Constants */ 32729); /* harmony import */ var _segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../segmentation/vascular-mask-compute */ 72024); /* harmony import */ var _vtk_shaders__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../vtk/shaders */ 2951); /* harmony import */ var _shaders_vascular_mask_frag_glsl__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./shaders/vascular-mask.frag.glsl */ 63143); /* harmony import */ var _volume_actor__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./volume-actor */ 68976); // GPU multi-input vascular masking: the label mask rides as the mapper's // second input and a //VTK::CustomColorMix shader replacement applies // per-class presentation, leaving the CT scalars untouched. const VASCULAR_MASK_FEATURE = 'vascular-mask'; // Must match vtkVolumeFS.glsl byte-for-byte; the spec asserts it does. const CUSTOM_COLOR_MIX_ANCHOR = '//VTK::CustomColorMix'; const PREVIEW_BLUE = [0.2, 0.4, 1]; // Keyed by mapper so phase switches (which rebuild mappers) drop stale attachments. const attachments = new WeakMap(); function getMaskMapper(viewport) { const actor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_9__.getVolumeActor)(viewport); const mapper = actor?.getMapper(); if (!mapper) return undefined; // The shared mapper never allocates textures for inputs beyond 0. if (mapper.getClassName?.() === 'vtkSharedVolumeMapper') { console.warn('vascular-mask-gpu: viewport still uses the shared mapper, cannot attach'); return undefined; } return mapper; } /** The TF doubles as the shader's label decode — its range must stay pinned * to [0, 2], so all three class points are always present. */ function writeSegOpacityPoints(segOpacity, outlierOpacity) { segOpacity.removeAllPoints(); segOpacity.addPoint(_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS.background, 0); segOpacity.addPoint(_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS.vessel, 1); segOpacity.addPoint(_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS.outlier, outlierOpacity); } function installMaskShader(mapper, mode) { const modeValue = mode === 'preview' ? 1 : 2; (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_7__.setShaderReplacement)(mapper, VASCULAR_MASK_FEATURE, (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_7__.fragmentReplacement)(CUSTOM_COLOR_MIX_ANCHOR, `#define VASCULAR_MASK_MODE ${modeValue}\n${_shaders_vascular_mask_frag_glsl__WEBPACK_IMPORTED_MODULE_8__["default"]}`, { replaceFirst: true })); } /** The mask must mirror the CT's geometry exactly — vtk marches one ray in * the first input's index space. */ function buildMaskImageData(ctImageData, labelData) { const maskImageData = _kitware_vtk_js_Common_DataModel_ImageData__WEBPACK_IMPORTED_MODULE_1__["default"].newInstance(); maskImageData.setDimensions(ctImageData.getDimensions()); maskImageData.setSpacing(ctImageData.getSpacing()); maskImageData.setOrigin(ctImageData.getOrigin()); maskImageData.setDirection(ctImageData.getDirection()); const scalars = _kitware_vtk_js_Common_Core_DataArray__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance({ name: 'vascularMaskLabels', numberOfComponents: 1, values: labelData }); maskImageData.getPointData().setScalars(scalars); return { maskImageData, scalars }; } function isVascularGpuMaskAttached(viewport) { const actor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_9__.getVolumeActor)(viewport); const mapper = actor?.getMapper(); return !!mapper && attachments.has(mapper); } /** True when the attached mask came from an exact full-resolution run. */ function isVascularGpuMaskExact(viewport) { const actor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_9__.getVolumeActor)(viewport); const mapper = actor?.getMapper(); const attachment = mapper && attachments.get(mapper); return !!attachment?.exact; } /** Omitting outlierOpacity keeps an existing attachment's value; fresh * attaches default to 0 and pick up the real value on the next preset apply. * Pass exact: false for low-res live-preview labels. */ function attachVascularGpuMask(viewport, labelData, mode, outlierOpacity, exact = true) { const actor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_9__.getVolumeActor)(viewport); const mapper = getMaskMapper(viewport); if (!actor || !mapper) return false; const ctImageData = mapper.getInputData(0); if (!ctImageData) return false; const [dimX, dimY, dimZ] = ctImageData.getDimensions(); if (labelData.length !== dimX * dimY * dimZ) { console.warn('vascular-mask-gpu: label buffer does not match the CT voxel count'); return false; } const existing = attachments.get(mapper); if (existing) { // Swap the label buffer in place so the CT texture's cache entry stays untouched. existing.scalars.setData(labelData); existing.scalars.modified(); existing.maskImageData.modified(); existing.exact = exact; setVascularGpuMaskMode(viewport, mode); if (outlierOpacity !== undefined) setVascularGpuMaskOutlierOpacity(viewport, outlierOpacity); // The setters only render on change; a same-mode label swap still needs a repaint. viewport.render(); return true; } const { maskImageData, scalars } = buildMaskImageData(ctImageData, labelData); const property = actor.getProperty(); const initialOutlierOpacity = outlierOpacity ?? 0; const segOpacity = _kitware_vtk_js_Common_DataModel_PiecewiseFunction__WEBPACK_IMPORTED_MODULE_2__["default"].newInstance(); writeSegOpacityPoints(segOpacity, initialOutlierOpacity); // Outliers are unlit but sample the CT color ramp directly in the shader // (see vascular-mask.frag.glsl) — this TF only needs background/vessel for // the invisible-background early-out and the preview-mode blue highlight. const segColor = _kitware_vtk_js_Rendering_Core_ColorTransferFunction__WEBPACK_IMPORTED_MODULE_3__["default"].newInstance(); segColor.addRGBPoint(_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS.background, 0, 0, 0); segColor.addRGBPoint(_segmentation_vascular_mask_compute__WEBPACK_IMPORTED_MODULE_6__.VASCULAR_MASK_LABELS.vessel, ...PREVIEW_BLUE); const previousColorMixPreset = property.getColorMixPreset(); property.setColorMixPreset(_kitware_vtk_js_Rendering_Core_VolumeProperty_Constants__WEBPACK_IMPORTED_MODULE_5__.ColorMixPreset.CUSTOM); property.setForceNearestInterpolation(1, true); property.setRGBTransferFunction(1, segColor); property.setScalarOpacity(1, segOpacity); // Match the CT's unit distance so the baked opacity correction treats both alike. property.setScalarOpacityUnitDistance(1, property.getScalarOpacityUnitDistance(0)); // vtk's render loop reads a per-input property for every valid input and // crashes if slot 1 is empty, even though all TF config lives on slot 0. // NEAREST keeps label texels exact. Safe to leave behind after detach. const actorProperties = actor.getProperties(); let maskProperty = actorProperties[1]; if (!maskProperty) { maskProperty = _kitware_vtk_js_Rendering_Core_VolumeProperty__WEBPACK_IMPORTED_MODULE_4__["default"].newInstance(); actor.setProperty(1, maskProperty); } maskProperty.setInterpolationTypeToNearest(); // addInputData grows to port 1, or refills it after a previous detach. mapper.addInputData(maskImageData); installMaskShader(mapper, mode); attachments.set(mapper, { exact, maskImageData, mode, outlierOpacity: initialOutlierOpacity, previousColorMixPreset, scalars, segOpacity }); viewport.render(); return true; } /** Swaps the compiled shader variant — a one-off recompile. */ function setVascularGpuMaskMode(viewport, mode) { const mapper = getMaskMapper(viewport); const attachment = mapper && attachments.get(mapper); if (!mapper || !attachment || attachment.mode === mode) return; attachment.mode = mode; installMaskShader(mapper, mode); viewport.render(); } /** Rides the component-1 opacity TF — a TF-texture rebuild, no recompile. */ function setVascularGpuMaskOutlierOpacity(viewport, outlierOpacity) { const mapper = getMaskMapper(viewport); const attachment = mapper && attachments.get(mapper); if (!attachment || attachment.outlierOpacity === outlierOpacity) return; attachment.outlierOpacity = outlierOpacity; writeSegOpacityPoints(attachment.segOpacity, outlierOpacity); viewport.render(); } /** The component-1 TFs stay on the property — unread at one component. */ function detachVascularGpuMask(viewport) { const actor = (0,_volume_actor__WEBPACK_IMPORTED_MODULE_9__.getVolumeActor)(viewport); const mapper = getMaskMapper(viewport); const attachment = mapper && attachments.get(mapper); if (!actor || !mapper || !attachment) return; // undefined empties the port: render skips it and a re-attach can refill it. mapper.setInputData(undefined, 1); (0,_vtk_shaders__WEBPACK_IMPORTED_MODULE_7__.removeShaderReplacement)(mapper, VASCULAR_MASK_FEATURE); const property = actor.getProperty(); property.setColorMixPreset(attachment.previousColorMixPreset); property.setForceNearestInterpolation(1, false); attachments.delete(mapper); viewport.render(); } /***/ }, /***/ 66174 /*!***********************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/vasculardefault-osirix-clut.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ VASCULARDEFAULT_OSIRIX_CLUT: () => (/* binding */ VASCULARDEFAULT_OSIRIX_CLUT) /* harmony export */ }); /** Vascular rendering CLUT exported from OsiriX (CLUT_osirix_vascular_rendering.plist), * converted from the .plist to this JSON-shaped constant. */ const VASCULARDEFAULT_OSIRIX_CLUT = { colors: [[{ blue: 0, green: 0, red: 0 }, { blue: 0.045_229_598_879_814_148, green: 0.130_792_096_257_209_78, red: 0.986_617_326_736_450_2 }, { blue: 0.275_571_227_073_669_43, green: 0.604_367_315_769_195_56, red: 0.992_038_011_550_903_32 }, { blue: 0.920_388_936_996_459_96, green: 0.972_010_314_464_569_09, red: 0.999_381_184_577_941_89 }, { blue: 1, green: 1, red: 1 }]], curves: [[{ x: -463.072_937_011_718_75, y: 0 }, { x: 215.275_497_436_523_44, y: 0 }, { x: 419.681_152_343_75, y: 0.528_467_833_995_819_09 }, { x: 588.222_229_003_906_25, y: 0.970_223_009_586_334_23 }, { x: 1899.497_314_453_125, y: 0.970_223_009_586_334_23 }]] }; /***/ }, /***/ 408 /*!*********************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/viewport-rays.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ rayFromCamera: () => (/* binding */ rayFromCamera), /* harmony export */ rayFromSlicePlane: () => (/* binding */ rayFromSlicePlane), /* harmony export */ slabAxesForViewport: () => (/* binding */ slabAxesForViewport) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** Perspective pick ray: starts at the camera, points toward the click on the focal plane. * Direction is not normalized; t=1 lands on the focal plane. */ function rayFromCamera(viewport, screenPos) { const cameraPos = viewport.getCamera().position; if (!cameraPos) return undefined; const focal = viewport.canvasToWorld(screenPos); if (!focal) return undefined; return { direction: [focal[0] - cameraPos[0], focal[1] - cameraPos[1], focal[2] - cameraPos[2]], origin: [cameraPos[0], cameraPos[1], cameraPos[2]] }; } /** Parallel pick ray: starts on the slice plane at the click, points along the slab normal. * Direction is unit-length; t=0 sits on the slice plane. */ function rayFromSlicePlane(viewport, screenPos) { const sliceWorld = viewport.canvasToWorld(screenPos); if (!sliceWorld) return undefined; const normal = viewport.getCamera().viewPlaneNormal; if (!normal) return undefined; return { direction: [normal[0], normal[1], normal[2]], origin: [sliceWorld[0], sliceWorld[1], sliceWorld[2]] }; } /** Right and up unit vectors that span the MPR slab plane. * right = normalize(viewUp x viewPlaneNormal); up = viewUp. */ function slabAxesForViewport(viewport) { const camera = viewport.getCamera(); const viewUp = camera.viewUp; const normal = camera.viewPlaneNormal; if (!viewUp || !normal) return undefined; const right = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(right, viewUp, normal); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(right, right); return { right: [right[0], right[1], right[2]], up: [viewUp[0], viewUp[1], viewUp[2]] }; } /***/ }, /***/ 63420 /*!**********************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/viewport-types.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getMprViewport: () => (/* binding */ getMprViewport), /* harmony export */ isBaseVolumeViewportLike: () => (/* binding */ isBaseVolumeViewportLike) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 93667); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 50600); /** Structural check for BaseVolumeViewport. */ function isBaseVolumeViewportLike(viewport) { return !!viewport && typeof viewport === 'object' && 'render' in viewport && typeof viewport.render === 'function' && 'setProperties' in viewport && typeof viewport.setProperties === 'function'; } /** Narrows to a parallel/MPR VolumeViewport (excluding the 3D subclass). */ function getMprViewport(viewport) { return viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"] && !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"]) ? viewport : undefined; } /***/ }, /***/ 86880 /*!************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/viewport-widgets.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ clearViewportWidgets: () => (/* binding */ clearViewportWidgets), /* harmony export */ removeViewportWidget: () => (/* binding */ removeViewportWidget) /* harmony export */ }); // The `instanceof Map` guard tolerates deep-mocked viewports in tests and // post-disable viewports with no widget Map. function widgetMap(viewport) { const widgets = viewport.viewportWidgets; return widgets instanceof Map ? widgets : undefined; } function removeViewportWidget(viewport, widgetId) { widgetMap(viewport)?.delete(widgetId); } function clearViewportWidgets(viewport) { widgetMap(viewport)?.clear(); } /***/ }, /***/ 68976 /*!********************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/volume-actor.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getVolumeActor: () => (/* binding */ getVolumeActor) /* harmony export */ }); // Extracted from cornerstone-helpers so vascular-mask-gpu can use it without // an import cycle; re-exported from cornerstone-helpers for existing importers. const getVolumeActor = viewport => { const actors = viewport.getActors(); const volumeEntry = actors.find(actorEntry => actorEntry.actor && actorEntry.referencedId?.startsWith(viewport.getVolumeId()) === true); if (!volumeEntry) { console.warn('No volume entry found in 3D viewport actors', actors); return; } return volumeEntry.actor; }; /***/ }, /***/ 60060 /*!*************************************************!*\ !*** ./libs/utils/src/lib/debug/debug-flags.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEBUG_FLAGS: () => (/* binding */ DEBUG_FLAGS), /* harmony export */ getAllDebugFlags: () => (/* binding */ getAllDebugFlags), /* harmony export */ getDebugFlagByName: () => (/* binding */ getDebugFlagByName) /* harmony export */ }); // Registry of valid debug flags and their defaults. // localStorage acts as an optional override layer on top of the registry. // Storage format: one JSON object under the `__TVCT_DEBUG__` key: // // localStorage.setItem('__TVCT_DEBUG__', JSON.stringify({ postProcess: true })); // location.reload(); // // To disable everything: // // localStorage.removeItem('__TVCT_DEBUG__'); location.reload(); // // Parsed once per page load, then every subsequent call is a record lookup. const DEBUG_FLAGS = { postProcess: false, showShell: false }; const STORAGE_KEY = '__TVCT_DEBUG__'; let cached; function loadFlags() { const merged = { ...DEBUG_FLAGS }; try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return merged; const parsed = JSON.parse(raw); if (!parsed || typeof parsed !== 'object') return merged; for (const [key, value] of Object.entries(parsed)) { if (key in DEBUG_FLAGS && typeof value === 'boolean') { merged[key] = value; } } return merged; } catch { return merged; } } function getAllDebugFlags() { cached ??= loadFlags(); return cached; } function getDebugFlagByName(key) { return getAllDebugFlags()[key] === true; } /***/ }, /***/ 46401 /*!*******************************************!*\ !*** ./libs/utils/src/lib/debug/index.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DEBUG_FLAGS: () => (/* reexport safe */ _debug_flags__WEBPACK_IMPORTED_MODULE_0__.DEBUG_FLAGS), /* harmony export */ getAllDebugFlags: () => (/* reexport safe */ _debug_flags__WEBPACK_IMPORTED_MODULE_0__.getAllDebugFlags), /* harmony export */ getDebugFlagByName: () => (/* reexport safe */ _debug_flags__WEBPACK_IMPORTED_MODULE_0__.getDebugFlagByName) /* harmony export */ }); /* harmony import */ var _debug_flags__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./debug-flags */ 60060); /***/ }, /***/ 14007 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/dicom/dicom-image-loader.token.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DICOM_IMAGE_LOADER: () => (/* binding */ DICOM_IMAGE_LOADER) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _dicom_image_loader_dev__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../dicom-image-loader-dev */ 99763); // eslint-disable-next-line @nx/enforce-module-boundaries const DICOM_IMAGE_LOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('DICOM_IMAGE_LOADER', { factory: () => _dicom_image_loader_dev__WEBPACK_IMPORTED_MODULE_1__["default"] }); /***/ }, /***/ 77983 /*!****************************************************************!*\ !*** ./libs/utils/src/lib/dicom/dicom-instances-validation.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MODALITY_CT_ERROR_MESSAGE: () => (/* binding */ MODALITY_CT_ERROR_MESSAGE), /* harmony export */ isViewableModality: () => (/* binding */ isViewableModality), /* harmony export */ normalizeModality: () => (/* binding */ normalizeModality), /* harmony export */ validateCtModality: () => (/* binding */ validateCtModality), /* harmony export */ validateInstances: () => (/* binding */ validateInstances) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/types */ 25575); const IMAGE_TYPE_TAG_ID = '00080008'; const MODALITY_CT_ERROR_MESSAGE = 'All instances must have Modality of type CT.'; const createInitialErrors = () => ({ imageOrientationPatientError: false, localizerError: false, modalityError: false, multiphaseError: false, pixelSpacingError: false, sliceThicknessError: false }); const hasLocalizerImageType = metadata => { const imageTypeValues = metadata[IMAGE_TYPE_TAG_ID]?.Value; if (!Array.isArray(imageTypeValues)) { return false; } return imageTypeValues.some(value => String(value).toUpperCase().includes('LOCALIZER')); }; const isStrictCtModality = modality => { return String(modality ?? '').trim().toUpperCase() === 'CT'; }; const validateCtModality = modality => { return isStrictCtModality(modality) ? [] : [MODALITY_CT_ERROR_MESSAGE]; }; const normalizeModality = modality => String(modality ?? '').trim().toUpperCase(); /** * Modalities the viewer can open: CT volumes, and OT for tvCT analysis series. Instance * validation can still reject an individual CT series, so this rules series out, never in. */ const isViewableModality = modality => { const normalized = normalizeModality(modality); return normalized === 'CT' || normalized === 'OT'; }; const createInitialMultiphaseState = () => ({ maxNumberOfPhases: undefined, phaseVectors: new Set(), triggerTimes: new Set() }); const updateErrorsForInstance = (errors, metadata) => { const modality = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.Modality); const pixelSpacing = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.PixelSpacing); const sliceThickness = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.SliceThickness); const imageOrientationPatient = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.ImageOrientationPatient); if (validateCtModality(modality).length > 0) { errors.modalityError = true; } if (hasLocalizerImageType(metadata)) { errors.localizerError = true; } if (!pixelSpacing) { errors.pixelSpacingError = true; } if (!sliceThickness) { errors.sliceThicknessError = true; } if (!imageOrientationPatient) { errors.imageOrientationPatientError = true; } }; const updateMultiphaseState = (state, metadata) => { const triggerTime = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TriggerTime); if (triggerTime !== undefined && triggerTime !== null) { state.triggerTimes.add(String(triggerTime)); } const phaseVector = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.PhaseVector); if (phaseVector !== undefined && phaseVector !== null) { state.phaseVectors.add(JSON.stringify(phaseVector)); } const numberOfPhases = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.NumberOfPhases); if (typeof numberOfPhases === 'number') { state.maxNumberOfPhases = state.maxNumberOfPhases === undefined ? numberOfPhases : Math.max(state.maxNumberOfPhases, numberOfPhases); } }; const applyMultiphaseResult = (errors, state) => { const hasExplicitMultiphase = state.maxNumberOfPhases !== undefined && state.maxNumberOfPhases > 1; const hasMultipleTemporalValues = state.triggerTimes.size > 1 || state.phaseVectors.size > 1; if (hasExplicitMultiphase || hasMultipleTemporalValues) { errors.multiphaseError = true; } }; const validateInstances = instances => { const errors = createInitialErrors(); const multiphaseState = createInitialMultiphaseState(); for (const instance of instances) { const metadata = instance.metadata; updateErrorsForInstance(errors, metadata); updateMultiphaseState(multiphaseState, metadata); } applyMultiphaseResult(errors, multiphaseState); return getErrorMessages(errors); }; const getErrorMessages = errors => { const errorMessages = []; if (errors.modalityError) { errorMessages.push(MODALITY_CT_ERROR_MESSAGE); } if (errors.pixelSpacingError) { errorMessages.push('PixelSpacing is required field for all instances.'); } if (errors.sliceThicknessError) { errorMessages.push('SliceThickness is required field for all instances.'); } if (errors.imageOrientationPatientError) { errorMessages.push('ImageOrientationPatient is required field for all instances.'); } if (errors.localizerError) { errorMessages.push('LOCALIZER images are not supported.'); } if (errors.multiphaseError) { errorMessages.push('Multiphase data is not supported.'); } return errorMessages; }; /***/ }, /***/ 67227 /*!*****************************************************!*\ !*** ./libs/utils/src/lib/dicom/extract-dicom10.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractDicomPart10: () => (/* binding */ extractDicomPart10) /* harmony export */ }); function extractDicomPart10(multipartBuffer, options = {}) { // 1. Find Double CRLF (end of MIME part headers) const crlfPattern = [Number('0x0d'), Number('0x0a'), Number('0x0d'), Number('0x0a')]; const endOfHeadersIndex = findBytePattern(multipartBuffer, crlfPattern, 12_000); if (endOfHeadersIndex === -1) { return recoverFromDicmOffset(multipartBuffer); } const startOfData = endOfHeadersIndex + 4; // 2. Binary search for Content-Length const headerView = multipartBuffer.subarray(0, startOfData); const contentLength = findContentLength(headerView); const boundary = getBoundaryFromContentType(options.contentType) || getBoundaryFromMultipartBody(multipartBuffer); let dicomData; if (contentLength && startOfData + contentLength <= multipartBuffer.length) { dicomData = multipartBuffer.subarray(startOfData, startOfData + contentLength); } else if (boundary) { const boundaryPattern = new TextEncoder().encode(`\r\n--${boundary}`); const boundaryIndex = findBytePattern(multipartBuffer, [...boundaryPattern], multipartBuffer.length, startOfData); const endIndex = boundaryIndex === -1 ? multipartBuffer.length : boundaryIndex; dicomData = multipartBuffer.subarray(startOfData, endIndex); } else { const genericBoundaryIndex = findGenericBoundaryIndex(multipartBuffer, startOfData); const endIndex = genericBoundaryIndex === -1 ? multipartBuffer.length : genericBoundaryIndex; dicomData = multipartBuffer.subarray(startOfData, endIndex); } dicomData = trimLeadingCrlf(dicomData); // 3. DICM Alignment const dicmPattern = [0x44, 0x49, 0x43, Number('0x4d')]; const dicmIndex = findBytePattern(dicomData, dicmPattern, 1024); if (dicmIndex >= 128) { return dicomData.subarray(dicmIndex - 128); } if (dicmIndex >= 0) { // DICM found but fewer than 128 bytes precede it (e.g. CRLF bytes were // trimmed). Reconstruct a proper Part 10 file: zero-filled preamble + // DICM magic + tag data so downstream code can rely on offset 132. const tagData = dicomData.subarray(dicmIndex + 4); const out = new Uint8Array(132 + tagData.length); out[128] = 0x44; out[129] = 0x49; out[130] = 0x43; out[131] = 0x4d; out.set(tagData, 132); return out; } return dicomData; } function recoverFromDicmOffset(buffer) { const dicmPattern = [0x44, 0x49, 0x43, Number('0x4d')]; const dicmIndex = findBytePattern(buffer, dicmPattern, buffer.length); if (dicmIndex === -1) { throw new Error('Could not extract DICOM payload from multipart response.'); } const alignedStart = dicmIndex >= 128 ? dicmIndex - 128 : dicmIndex; const candidate = buffer.subarray(alignedStart); const genericBoundaryIndex = findGenericBoundaryIndex(candidate, 0); if (genericBoundaryIndex === -1) { return candidate; } return candidate.subarray(0, genericBoundaryIndex); } function trimLeadingCrlf(buffer) { let index = 0; while (index + 1 < buffer.length && buffer[index] === Number('0x0d') && buffer[index + 1] === Number('0x0a')) { index += 2; } return index > 0 ? buffer.subarray(index) : buffer; } function findGenericBoundaryIndex(buffer, start) { for (let index = Math.max(start, 0); index < buffer.length - 6; index++) { const startsWithCrlfDashDash = buffer[index] === Number('0x0d') && buffer[index + 1] === Number('0x0a') && buffer[index + 2] === Number('0x2d') && buffer[index + 3] === Number('0x2d'); if (!startsWithCrlfDashDash) { continue; } const lineEnd = findBytePattern(buffer, [Number('0x0d'), Number('0x0a')], buffer.length, index + 4); if (lineEnd === -1) { continue; } const boundaryLine = new TextDecoder('ascii', { fatal: false }).decode(buffer.subarray(index + 4, lineEnd)); if (isLikelyBoundaryLine(boundaryLine)) { return index; } } return -1; } function isLikelyBoundaryLine(line) { const normalized = line.trim(); if (!normalized) { return false; } const boundaryToken = normalized.endsWith('--') ? normalized.slice(0, -2) : normalized; if (!boundaryToken || boundaryToken.length > 70) { return false; } return /^[0-9A-Za-z'()+_,./:=?-]+$/.test(boundaryToken); } function getBoundaryFromContentType(contentType) { if (!contentType) { return; } const boundaryMatch = contentType.match(/boundary=(?:"([^"]+)"|([^;]+))/i); const boundary = boundaryMatch?.[1] || boundaryMatch?.[2]; return boundary?.trim(); } function getBoundaryFromMultipartBody(buffer) { const firstBoundaryAtStart = buffer.length > 2 && buffer[0] === Number('0x2d') && buffer[1] === Number('0x2d'); if (firstBoundaryAtStart) { const firstLineBreak = findBytePattern(buffer, [Number('0x0d'), Number('0x0a')], 1024, 2); if (firstLineBreak !== -1) { const boundaryLine = new TextDecoder('ascii', { fatal: false }).decode(buffer.subarray(2, firstLineBreak)); const boundary = boundaryLine.trim(); if (boundary) { return boundary; } } } const boundaryMarker = [Number('0x0d'), Number('0x0a'), Number('0x2d'), Number('0x2d')]; const boundaryStart = findBytePattern(buffer, boundaryMarker, 4096); if (boundaryStart === -1) { return; } const lineStart = boundaryStart + boundaryMarker.length; const lineEnd = findBytePattern(buffer, [Number('0x0d'), Number('0x0a')], 4096, lineStart); if (lineEnd === -1 || lineEnd <= lineStart) { return; } const boundaryLine = new TextDecoder('ascii', { fatal: false }).decode(buffer.subarray(lineStart, lineEnd)); return boundaryLine.trim(); } function findBytePattern(buffer, pattern, limit, start = 0) { const searchLimit = Math.min(buffer.length, limit) - pattern.length; for (let index = start; index <= searchLimit; index++) { if (pattern.every((byte, index_) => buffer[index + index_] === byte)) { return index; } } return -1; } function findContentLength(buffer) { const target = 'content-length:'; const headerString = new TextDecoder('ascii').decode(buffer).toLowerCase(); const index = headerString.indexOf(target); if (index === -1) return; const line = headerString.slice(Math.max(0, index + target.length)).split('\r')[0]; if (!line) return; const parsed = Number.parseInt(line.trim(), 10); return Number.isNaN(parsed) ? undefined : parsed; } /***/ }, /***/ 92627 /*!********************************************************!*\ !*** ./libs/utils/src/lib/dicom/extract-pixel-data.ts ***! \********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractPixelData: () => (/* binding */ extractPixelData) /* harmony export */ }); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dicom_parser__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @tomoverse/types */ 25575); function extractPixelData(buffer) { const dicomByteArray = new Uint8Array(buffer); const dataset = dicom_parser__WEBPACK_IMPORTED_MODULE_0___default().parseDicom(dicomByteArray); const meta = dataset; const rows = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_2__.getTagValue)(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.DicomTagId.Rows) ?? 512; const cols = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_2__.getTagValue)(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.DicomTagId.Columns) ?? 512; const bits = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_2__.getTagValue)(meta, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_1__.DicomTagId.BitsAllocated) ?? 16; const element = dataset.elements['x7fe00010']; if (!element) throw new Error('No pixel data element found'); const offset = element.dataOffset + dicomByteArray.byteOffset; const length = rows * cols * Math.max(1, Math.floor(bits / 8)); return new Uint8Array(dicomByteArray.buffer, offset, Math.min(length, dicomByteArray.buffer.byteLength - offset)); } /***/ }, /***/ 1712 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/dicom/extract-window-metadata.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractWindowMetadata: () => (/* binding */ extractWindowMetadata) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/types */ 25575); function extractWindowMetadata(metadata, defaults) { const rescaleIntercept = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.RescaleIntercept); const bitsStored = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.BitsStored); const windowLevel = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.WindowCenter); const windowWidth = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.WindowWidth); const windowLevels = metadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.WindowCenter]?.Value?.map(Number).filter(element => Number.isFinite(element)) || []; const windowWidths = metadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.WindowWidth]?.Value?.map(Number).filter(element => Number.isFinite(element)) || []; const maxPixelSize = bitsStored === undefined ? undefined : Math.pow(2, Number(bitsStored)) - 1; return { maxPixelSize, rescaleIntercept: Number(rescaleIntercept ?? 0), windowLevel: Number(windowLevel ?? defaults.level), windowLevels, windowWidth: Number(windowWidth ?? defaults.width), windowWidths }; } /***/ }, /***/ 50277 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/dicom/format-dicom-date.helper.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ toDicomDate: () => (/* binding */ toDicomDate) /* harmony export */ }); /** Formats a `Date` as a DICOM `YYYYMMDD` string (the inverse of `parseDicomDate`). */ function toDicomDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}${month}${day}`; } /***/ }, /***/ 18116 /*!**********************************************************!*\ !*** ./libs/utils/src/lib/dicom/normalize-series-uid.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ normalizeSeriesUid: () => (/* binding */ normalizeSeriesUid) /* harmony export */ }); function normalizeSeriesUid(seriesUid) { return String(seriesUid ?? '').trim(); } /***/ }, /***/ 32495 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/dicom/parse-dicom-date.helper.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ parseDicomDate: () => (/* binding */ parseDicomDate) /* harmony export */ }); const parseDicomDate = value => { if (!value || !/^\d{8}$/.test(value)) { return undefined; } const year = Number(value.slice(0, 4)); const month = Number(value.slice(4, 6)) - 1; const day = Number(value.slice(6, 8)); return new Date(year, month, day); }; /***/ }, /***/ 21423 /*!*******************************************************!*\ !*** ./libs/utils/src/lib/dicom/windowing-presets.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ BASE_MPR_WL_PRESETS: () => (/* binding */ BASE_MPR_WL_PRESETS), /* harmony export */ DEFAULT_MAX_PIXELS: () => (/* binding */ DEFAULT_MAX_PIXELS), /* harmony export */ PRESET_NAME_PREFIX: () => (/* binding */ PRESET_NAME_PREFIX), /* harmony export */ buildDicomPresets: () => (/* binding */ buildDicomPresets), /* harmony export */ buildWindowDefaults: () => (/* binding */ buildWindowDefaults) /* harmony export */ }); const DEFAULT_MAX_PIXELS = 4096; const PRESET_NAME_PREFIX = 'Window'; const BASE_MPR_WL_PRESETS = [{ level: 50, name: 'Abdomen', width: 400 }, { level: 68, name: 'Abdomen Angio', width: 666 }, { level: 40, name: 'Calcium', width: 400 }, { level: 45, name: 'Head Angio', width: 684 }, { level: 35, name: 'Head Post Fossa', width: 200 }, { level: 120, name: 'Head', width: 300 }, { level: 125, name: 'Liver', width: 270 }, { level: -550, name: 'Lung', width: 1500 }, { level: 50, name: 'Mediastinum', width: 500 }, { level: 350, name: 'Ortho bone', width: 1200 }, { level: 200, name: 'Sinuses', width: 2000 }, { level: -10, name: 'Soft Tissue', width: 500 }, { level: 800, name: 'Spine Neuro', width: 3000 }, { level: 500, name: 'Vertabrae', width: 4000 }]; const buildDicomPresets = (windowWidths, windowLevels, namePrefix) => { const presets = []; const presetCount = Math.min(windowWidths.length, windowLevels.length); if (presetCount === 0) return []; for (let index = 0; index < presetCount; index++) { const level = windowLevels[index]; const width = windowWidths[index]; if (!level || !width) continue; presets.push({ level, name: `${namePrefix} ${index + 1}`, width }); } return presets; }; const buildWindowDefaults = (defaultPreset, dicomPreset) => { const defaultWindowWidth = dicomPreset?.width ?? defaultPreset.width; const defaultWindowLevel = dicomPreset?.level ?? defaultPreset.level; const defaultWindowPreset = dicomPreset?.name ?? defaultPreset.name; return { defaultWindowLevel, defaultWindowPreset, defaultWindowWidth }; }; /***/ }, /***/ 20165 /*!*******************************************!*\ !*** ./libs/utils/src/lib/drag-bounds.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ clampOffsetWithinBounds: () => (/* binding */ clampOffsetWithinBounds), /* harmony export */ resolveBoundaryRect: () => (/* binding */ resolveBoundaryRect) /* harmony export */ }); /* harmony import */ var _clamp_range__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clamp-range */ 19414); /** * Resolve an element or CSS selector to its on-screen rect. * A selector is matched against the nearest ancestor of `host` first, then document-wide. */ function resolveBoundaryRect(boundary, host) { if (boundary instanceof HTMLElement) { return boundary.getBoundingClientRect(); } if (typeof boundary === 'string' && boundary) { const element = host.closest(boundary) ?? host.ownerDocument.querySelector(boundary); return element?.getBoundingClientRect(); } return undefined; } /** * Clamp an `offset` so a box positioned at `anchor` stays fully inside `bounds`. */ function clampOffsetWithinBounds(offset, anchor, bounds) { return { x: (0,_clamp_range__WEBPACK_IMPORTED_MODULE_0__.clampRange)(offset.x, bounds.left - anchor.left, bounds.right - anchor.width - anchor.left), y: (0,_clamp_range__WEBPACK_IMPORTED_MODULE_0__.clampRange)(offset.y, bounds.top - anchor.top, bounds.bottom - anchor.height - anchor.top) }; } /***/ }, /***/ 63940 /*!**********************************************!*\ !*** ./libs/utils/src/lib/electron/index.ts ***! \**********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isElectron: () => (/* reexport safe */ _is_electron__WEBPACK_IMPORTED_MODULE_0__.isElectron) /* harmony export */ }); /* harmony import */ var _is_electron__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./is-electron */ 89913); /***/ }, /***/ 89913 /*!****************************************************!*\ !*** ./libs/utils/src/lib/electron/is-electron.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isElectron: () => (/* binding */ isElectron) /* harmony export */ }); const isElectron = () => typeof navigator !== 'undefined' && /Electron/.test(navigator.userAgent); /***/ }, /***/ 49618 /*!*******************************************!*\ !*** ./libs/utils/src/lib/export-json.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ exportToJsonFile: () => (/* binding */ exportToJsonFile) /* harmony export */ }); function exportToJsonFile(document, data, fileName) { try { const jsonString = JSON.stringify(data, (key, value) => { // Clear internal keys (e.g., __ngContext__) and DOM nodes if (/^__.*__$/.test(key) || value instanceof Node) { return; } return value; }, 2); const blob = new Blob([jsonString], { type: 'application/json' }); const objectUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.style.display = 'none'; link.href = objectUrl; link.download = fileName.endsWith('.json') ? fileName : `${fileName}.json`; document.body.append(link); link.click(); link.remove(); URL.revokeObjectURL(objectUrl); } catch (error) { console.error('Failed to export JSON file:', error); throw new Error('Serialization failed'); } } /***/ }, /***/ 66255 /*!******************************************************!*\ !*** ./libs/utils/src/lib/format-export-filename.ts ***! \******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ formatExportFileName: () => (/* binding */ formatExportFileName) /* harmony export */ }); function formatExportFileName(name) { const fallback = 'file'; const normalized = (name ?? fallback).trim(); if (!normalized) return fallback; return normalized.replaceAll(/[\\/:*?"<>|]/g, '_'); } /***/ }, /***/ 73442 /*!****************************************************!*\ !*** ./libs/utils/src/lib/generate-unique-name.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ generateUniqueName: () => (/* binding */ generateUniqueName) /* harmony export */ }); function generateUniqueName(existingItems, nameField, baseName) { const existingNames = new Set(existingItems.map(item => { const value = item[nameField]; return typeof value === 'string' ? value.trim() : ''; })); let counter = 1; let candidate = `${baseName} ${counter}`; while (existingNames.has(candidate)) { counter++; candidate = `${baseName} ${counter}`; } return candidate; } /***/ }, /***/ 28522 /*!*********************************************!*\ !*** ./libs/utils/src/lib/geometry/aabb.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ aabbCentreDepth: () => (/* binding */ aabbCentreDepth), /* harmony export */ aabbFromVec3s: () => (/* binding */ aabbFromVec3s), /* harmony export */ aabbFromVertices: () => (/* binding */ aabbFromVertices), /* harmony export */ aabbOverlap: () => (/* binding */ aabbOverlap), /* harmony export */ aabbToVec3s: () => (/* binding */ aabbToVec3s), /* harmony export */ aabbVolume: () => (/* binding */ aabbVolume), /* harmony export */ minDistanceToAABB: () => (/* binding */ minDistanceToAABB), /* harmony export */ projectedAabbArea: () => (/* binding */ projectedAabbArea), /* harmony export */ projectedAabbBounds2d: () => (/* binding */ projectedAabbBounds2d) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); // Axis-aligned bounding box (AABB): the smallest 3D box whose faces are // parallel to the world X/Y/Z axes that contains every point in a mesh. // We use it as a fast proxy for ray-vs-mesh tests: rejecting against the box // is six axis comparisons per ray, while a triangle-mesh test would scan // every face. The box is correct as a containment test only when the mesh is // convex (or convex-enough). For non-convex meshes the box has corners the // mesh doesn't fill. /** Volume of an AABB. */ function aabbVolume(bounds) { return (bounds[3] - bounds[0]) * (bounds[4] - bounds[1]) * (bounds[5] - bounds[2]); } function aabbFromVec3s(min, max) { const [minX, minY, minZ] = min; const [maxX, maxY, maxZ] = max; return [minX, minY, minZ, maxX, maxY, maxZ]; } function aabbToVec3s(aabb) { const [minX, minY, minZ, maxX, maxY, maxZ] = aabb; return [gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(minX, minY, minZ), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(maxX, maxY, maxZ)]; } /** Tight AABB of a flat XYZ vertex buffer. */ // eslint-disable-next-line sonarjs/cyclomatic-complexity function aabbFromVertices(vertices) { let minX = Infinity, minY = Infinity, minZ = Infinity; let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity; for (let index = 0; index < vertices.length; index += 3) { const x = vertices[index] ?? 0; const y = vertices[index + 1] ?? 0; const z = vertices[index + 2] ?? 0; if (x < minX) minX = x; if (x > maxX) maxX = x; if (y < minY) minY = y; if (y > maxY) maxY = y; if (z < minZ) minZ = z; if (z > maxZ) maxZ = z; } return [minX, minY, minZ, maxX, maxY, maxZ]; } /** 2D bounds of an AABB's 8 corners after userMatrix and a 2D projection. * Returns undefined if every corner failed to project. */ function projectedAabbBounds2d(bounds, userMatrix, project) { const [minX_, minY_, minZ_, maxX_, maxY_, maxZ_] = bounds; const corners = [[minX_, minY_, minZ_], [maxX_, minY_, minZ_], [minX_, maxY_, minZ_], [maxX_, maxY_, minZ_], [minX_, minY_, maxZ_], [maxX_, minY_, maxZ_], [minX_, maxY_, maxZ_], [maxX_, maxY_, maxZ_]]; const world = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); let minX = Infinity, minY = Infinity; let maxX = -Infinity, maxY = -Infinity; for (const corner of corners) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.transformMat4(world, corner, userMatrix); const p = project(world); if (!p) continue; if (p[0] < minX) minX = p[0]; if (p[0] > maxX) maxX = p[0]; if (p[1] < minY) minY = p[1]; if (p[1] > maxY) maxY = p[1]; } if (minX === Infinity) return undefined; return { maxX, maxY, minX, minY }; } /** Area of the AABB's projection through userMatrix onto the slab plane. * Used by MPR ranking to pick the smallest cross-section. */ function projectedAabbArea(bounds, userMatrix, axes) { const r = projectedAabbBounds2d(bounds, userMatrix, world => [world[0] * axes.right[0] + world[1] * axes.right[1] + world[2] * axes.right[2], world[0] * axes.up[0] + world[1] * axes.up[1] + world[2] * axes.up[2]]); return r ? (r.maxX - r.minX) * (r.maxY - r.minY) : 0; } /** Depth of the AABB's centre along a world ray, in ray-direction-length t-units. * Used for back-most ranking when ray-vs-AABB precision is unreliable. */ function aabbCentreDepth(bounds, userMatrix, ray) { const [minX, minY, minZ, maxX, maxY, maxZ] = bounds; const localCentre = [(minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2]; const worldCentre = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.transformMat4(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), localCentre, userMatrix); const dx = worldCentre[0] - ray.origin[0]; const dy = worldCentre[1] - ray.origin[1]; const dz = worldCentre[2] - ray.origin[2]; const directionLengthSquared = ray.direction[0] * ray.direction[0] + ray.direction[1] * ray.direction[1] + ray.direction[2] * ray.direction[2]; if (directionLengthSquared === 0) return 0; return (dx * ray.direction[0] + dy * ray.direction[1] + dz * ray.direction[2]) / directionLengthSquared; } function minDistanceToAABB(point, aabb) { const [minX, minY, minZ, maxX, maxY, maxZ] = aabb; // Closest point on the AABB to the query point, then distance to it const closest = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(Math.max(minX, Math.min(point[0], maxX)), Math.max(minY, Math.min(point[1], maxY)), Math.max(minZ, Math.min(point[2], maxZ))); return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(point, closest); } function aabbOverlap(a, b) { const [[minX1, minY1, minZ1, maxX1, maxY1, maxZ1], [minX2, minY2, minZ2, maxX2, maxY2, maxZ2]] = [a, b]; return minX1 <= maxX2 && maxX1 >= minX2 && minY1 <= maxY2 && maxY1 >= minY2 && minZ1 <= maxZ2 && maxZ1 >= minZ2; } /***/ }, /***/ 66706 /*!************************************************************!*\ !*** ./libs/utils/src/lib/geometry/add-point-to-spline.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ addPointToSpline: () => (/* binding */ addPointToSpline) /* harmony export */ }); /* harmony import */ var _calculate_distance_on_path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./calculate-distance-on-path */ 67638); /* harmony import */ var _closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./closest-path-index-to-position */ 86710); function addPointToSpline(existing, path, newPoint) { // Adapted from `SplineTool::addPointToSplineAt()` const closest = (0,_closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__.closestPathIndexToPosition)(newPoint, path); if (closest.minIndex > path.length) { return { addedAt: existing.length, points: [...existing, newPoint] }; } if (closest.minIndex === 0) { return { addedAt: 0, points: [newPoint, ...existing] }; } const distanceAlongSpline = (0,_calculate_distance_on_path__WEBPACK_IMPORTED_MODULE_0__.calculateDistanceOnPath)(path, newPoint); const indexBefore = existing.findLastIndex(point => (0,_calculate_distance_on_path__WEBPACK_IMPORTED_MODULE_0__.calculateDistanceOnPath)(path, point) < distanceAlongSpline) + 1; return { addedAt: indexBefore, points: existing.toSpliced(indexBefore, 0, newPoint) }; } /***/ }, /***/ 69232 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/geometry/angulation-to-vector.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ angulationToVector: () => (/* binding */ angulationToVector) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _angles__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../angles */ 13413); function angulationToVector({ cc, rl }) { cc = (0,_angles__WEBPACK_IMPORTED_MODULE_1__.deg2rad)(cc); rl = (0,_angles__WEBPACK_IMPORTED_MODULE_1__.deg2rad)(rl); const vec = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(-Math.cos(cc) * Math.sin(rl), Math.cos(cc) * Math.cos(rl), -Math.sin(cc)); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(vec, vec); return vec; } /***/ }, /***/ 64469 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/geometry/annotation-plane-fade.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA: () => (/* binding */ ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA), /* harmony export */ ANNOTATION_VISIBLE_DISTANCE_MM: () => (/* binding */ ANNOTATION_VISIBLE_DISTANCE_MM), /* harmony export */ annotationPointInBand: () => (/* binding */ annotationPointInBand), /* harmony export */ signedDistanceToPlane: () => (/* binding */ signedDistanceToPlane) /* harmony export */ }); /** Half-width of the visibility band, in mm. */ const ANNOTATION_VISIBLE_DISTANCE_MM = 4; /** Alpha floor for a selected polyline rendered out-of-plane. */ const ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA = 0.5; /** * Signed perpendicular distance from a world-space point to a plane defined * by a point on the plane and a unit normal. Positive on the normal side. */ function signedDistanceToPlane(worldPoint, planePoint, planeNormal) { const [wx, wy, wz] = worldPoint; const [px, py, pz] = planePoint; const [nx, ny, nz] = planeNormal; return (wx - px) * nx + (wy - py) * ny + (wz - pz) * nz; } /** * Hard-cutoff visibility for point-shaped actors (control points, single * points, spline preview). Binary inside/outside the band, no gradient. */ function annotationPointInBand(worldPoint, planePoint, planeNormal, band = ANNOTATION_VISIBLE_DISTANCE_MM) { return Math.abs(signedDistanceToPlane(worldPoint, planePoint, planeNormal)) < band; } /***/ }, /***/ 7921 /*!*******************************************************!*\ !*** ./libs/utils/src/lib/geometry/axis-alignment.ts ***! \*******************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ autoAlignAxis: () => (/* binding */ autoAlignAxis), /* harmony export */ mostDistinctAxis: () => (/* binding */ mostDistinctAxis) /* harmony export */ }); /* harmony import */ var svd_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! svd-js */ 17826); /* harmony import */ var svd_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(svd_js__WEBPACK_IMPORTED_MODULE_0__); function getCenteredSamples(vertices, centroid, maxSamples) { const numberVertices = vertices.length / 3; const numberSamples = Math.min(maxSamples, numberVertices); const step = Math.max(1, Math.floor(numberVertices / numberSamples)); const A = Array.from({ length: numberSamples }); const [cx, cy, cz] = centroid; for (let index = 0; index < numberSamples; index++) { const index_ = index * step * 3; A[index] = [(vertices[index_] ?? 0) - cx, (vertices[index_ + 1] ?? 0) - cy, (vertices[index_ + 2] ?? 0) - cz]; } return A; } function autoAlignAxis(vertices, centroid) { const A = getCenteredSamples(vertices, centroid, 500); // Perform SVD to find principal components const { q, v } = (0,svd_js__WEBPACK_IMPORTED_MODULE_0__.SVD)(A, false, true); if (!q || !v || !v[0] || !v[1] || !v[2]) throw new Error('SVD failed to converge'); // Pick the axis of rotational symmetry: the singular value that stands out most // from the other two. For a rod that's the long axis (one large value, two small), // for a disc it's the thin axle (two large values, one small). const mainAxis = mostDistinctAxis(q); const mainAxisVec = [v[0][mainAxis] ?? 0, v[1][mainAxis] ?? 0, v[2][mainAxis] ?? 0]; // Align the symmetry axis to World Normal return { alignedVertices: vertices, rotationMatrix: getAlignmentMatrix(mainAxisVec, [0, 1, 0]) }; } /** * Index of the singular value that differs most from * the other two is the axis of rotational symmetry. */ function mostDistinctAxis(q) { const q0 = q[0] ?? 0; const q1 = q[1] ?? 0; const q2 = q[2] ?? 0; const d01 = Math.abs(q0 - q1); const d02 = Math.abs(q0 - q2); const d12 = Math.abs(q1 - q2); if (d01 > d12 && d02 > d12) return 0; if (d01 > d02 && d12 > d02) return 1; return 2; } /** * Generates a 4x4 rotation matrix that rotates 'source' vector to 'target' vector. */ function getAlignmentMatrix(source, target) { const [sx, sy, sz] = normalizeVector(source); const [tx, ty, tz] = target; const ux = sy * tz - sz * ty; const uy = sz * tx - sx * tz; const uz = sx * ty - sy * tx; const cosTheta = sx * tx + sy * ty + sz * tz; // Handle identity or 180-degree cases if (cosTheta > 0.9999) return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; if (cosTheta < -0.9999) return [-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; const k = 1 / (1 + cosTheta); return [ux * ux * k + cosTheta, ux * uy * k + uz, ux * uz * k - uy, 0, uy * ux * k - uz, uy * uy * k + cosTheta, uy * uz * k + ux, 0, uz * ux * k + uy, uz * uy * k - ux, uz * uz * k + cosTheta, 0, 0, 0, 0, 1]; } function normalizeVector(v) { const l = Math.hypot(v[0], v[1], v[2]) || 1; return [v[0] / l, v[1] / l, v[2] / l]; } /***/ }, /***/ 25257 /*!***********************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-angle-between-points.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateAngleBetweenPoints: () => (/* binding */ calculateAngleBetweenPoints) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _angles__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../angles */ 13413); function calculateAngleBetweenPoints(start, center, end) { const d1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), start, center); const d2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), end, center); // `vec3.angle()` would return 0 in most cases anyway, // but [0,0,0],[0,0,0] would return 90. if (gl_matrix__WEBPACK_IMPORTED_MODULE_0__.equals(d1, d2)) { return 0; } const angle = (0,_angles__WEBPACK_IMPORTED_MODULE_1__.rad2deg)(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.angle(d1, d2)); if (Number.isNaN(angle) || Math.abs(angle) < 0.1) { return 0; } return angle; } /***/ }, /***/ 68555 /*!*********************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-closed-spline-area.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateClosedSplineArea: () => (/* binding */ calculateClosedSplineArea) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function calculateClosedSplineArea(path, centroid, bestFitPlaneNormal) { // Integrate path to get length let d = 0; let lastPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...path[0]); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(lastPosition, lastPosition, centroid); let p = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(lastPosition, bestFitPlaneNormal); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(lastPosition, lastPosition, bestFitPlaneNormal, -1 * p); for (const position of path) { const currentPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...position); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(currentPosition, currentPosition, centroid); p = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(currentPosition, bestFitPlaneNormal); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(currentPosition, currentPosition, bestFitPlaneNormal, -1 * p); const crossProduct = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(crossProduct, currentPosition, lastPosition); d += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(crossProduct, bestFitPlaneNormal) * 0.5; lastPosition = currentPosition; } return Math.abs(d); } /***/ }, /***/ 10840 /*!********************************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-closed-spline-best-fit-normal.ts ***! \********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateClosedSplineBestFitNormal: () => (/* binding */ calculateClosedSplineBestFitNormal) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); function calculateClosedSplineBestFitNormal(path, centroid, stride = 10) { // calculate best fit plane normal using SVD power method (https://www.cs.cmu.edu/~avrim/598/chap3only.pdf) const skippedPath = path.filter((_, index) => index % stride === 0); let ata = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(0, 0, 0, 0, 0, 0, 0, 0, 0); for (const point of skippedPath) { const v = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(point[0] - centroid[0], point[1] - centroid[1], point[2] - centroid[2]); const m = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(v[0] * v[0], v[0] * v[1], v[0] * v[2], v[1] * v[0], v[1] * v[1], v[1] * v[2], v[2] * v[0], v[2] * v[1], v[2] * v[2]); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(ata, ata, m); } const v1 = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(1, 1, 1); for (let _ = 0; _ < 5; _++) { gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat3(v1, v1, ata); } gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(v1, v1); // Get second singular vector ata = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(0, 0, 0, 0, 0, 0, 0, 0, 0); for (const point of skippedPath) { const v = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(point[0] - centroid[0], point[1] - centroid[1], point[2] - centroid[2]); const p = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.dot(v, v1); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.scaleAndAdd(v, v, v1, -1 * p); const m = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(v[0] * v[0], v[0] * v[1], v[0] * v[2], v[1] * v[0], v[1] * v[1], v[1] * v[2], v[2] * v[0], v[2] * v[1], v[2] * v[2]); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(ata, ata, m); } const v2 = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromValues(1, 1, 1); for (let _ = 0; _ < 5; _++) { gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat3(v2, v2, ata); } gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(v2, v2); const normal = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.cross(normal, v1, v2); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(normal, normal); return normal; } /***/ }, /***/ 44465 /*!***********************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-closed-spline-height.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateClosedSplineHeight: () => (/* binding */ calculateClosedSplineHeight) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function calculateClosedSplineHeight(path, centroid, bestFitNormal) { let height = 0; for (const pointA of path) { const position1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...pointA); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(position1, position1, centroid); const h1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(position1, bestFitNormal); for (const pointB of path) { if (pointA !== pointB) { const position2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...pointB); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(position2, position2, centroid); height = Math.max(height, Math.abs(h1 + gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(position2, bestFitNormal))); } } } return height; } /***/ }, /***/ 14445 /*!****************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-coronal-angle.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ validateViewportAngle: () => (/* binding */ validateViewportAngle) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function validateViewportAngle(viewPlaneNormal, isPosterior) { let [CC, RL] = vec2Angle(viewPlaneNormal); if (isPosterior) { if (CC > 90 || CC < -90 || RL < 90 || RL > 270) { [CC, RL] = posteriorInvertVec2Angle(viewPlaneNormal); return [CC, RL, true]; } else { return [CC, RL, false]; } } else { if (CC > 90 || CC < -90 || RL > 90 || RL < -90) { [CC, RL] = invertVec2Angle(viewPlaneNormal); return [CC, RL, true]; } else { return [CC, RL, false]; } } } function vec2Angle(vector) { const CC = -Math.asin(vector[2]) / Math.PI * 180; const RL = Math.atan2(vector[0], -vector[1]) / Math.PI * 180; return [CC, RL]; } function invertVec2Angle(vector) { const rescaledZ = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(rescaledZ, vector, -1); const CC = -Math.asin(rescaledZ[2]) / Math.PI * 180; let RL = -Math.atan2(rescaledZ[0], rescaledZ[1]) / Math.PI * 180; if (RL > 90 || RL < -90) { RL += 180; if (RL > 90) RL -= 360; } return [CC, RL]; } function posteriorInvertVec2Angle(vector) { const rescaledZ = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(rescaledZ, vector, -1); let nCC = -Math.asin(rescaledZ[2]) / Math.PI * 180; let nRL = -Math.atan2(rescaledZ[0], rescaledZ[1]) / Math.PI * 180 + 180; if (nRL > 270 || nRL < 90) { nRL += 180; nCC *= -1; if (nRL > 270) nRL -= 360; } return [nCC, nRL]; } /***/ }, /***/ 91905 /*!*******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-curvature-radius.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateCurvatureRadius: () => (/* binding */ calculateCurvatureRadius) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _range__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../range */ 12896); /* harmony import */ var _closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./closest-path-index-to-position */ 86710); const ROLLING_AVERAGE_LENGTH = 10; function calculateCurvatureRadius(path, position) { // Adapted from `CurvaturePointTool::calculateRadiusOfCurvature()` const { minIndex: index } = (0,_closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_2__.closestPathIndexToPosition)(position, path); let previousPoint = path[0]; let distance = 0; const distances = [0]; for (const point of path.slice(1)) { distance += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(previousPoint, point); distances.push(distance); previousPoint = point; } function radiusOfCurvatureAt(index_) { let [index0, index1, index2] = [index_ - 2, index_, index_ + 2]; if (index0 < 0) { index0 = 0; index1 = 2; index2 = 4; } if (index2 >= path.length) { index0 = path.length - 5; index1 = path.length - 3; index2 = path.length - 1; } const d0 = distances[index0]; const d1 = distances[index1]; const d2 = distances[index2]; if (d0 === undefined || d1 === undefined || d2 === undefined) { return 0; } const p0 = path[index0]; const p1 = path[index1]; const p2 = path[index2]; if (!p0 || !p1 || !p2) { return 0; } const v = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(v, p2, p0); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(v, v, 1 / (d2 - d0)); const a = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(a, p0, p1, -2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(a, a, p2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(a, a, Math.pow(2 / (d2 - d0), 2)); const vNorm = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(v); const aNorm = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(a); const aDotV = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(v, a); return Math.pow(vNorm, 3) / Math.sqrt(Math.pow(vNorm, 2) * Math.pow(aNorm, 2) - Math.pow(aDotV, 2)); } if (distance <= ROLLING_AVERAGE_LENGTH) { return radiusOfCurvatureAt(index); } const pointDistance = distances[index] ?? 0; let [startDistance, endDistance] = [pointDistance - ROLLING_AVERAGE_LENGTH * 0.5, pointDistance + ROLLING_AVERAGE_LENGTH * 0.5]; if (startDistance < 0) { startDistance = 0; endDistance = ROLLING_AVERAGE_LENGTH; } if (endDistance > distance) { startDistance = distance - ROLLING_AVERAGE_LENGTH; endDistance = distance; } const startIndex = Math.round(pathIndexAtDistance(distances, startDistance)); const endIndex = Math.round(pathIndexAtDistance(distances, endDistance)); const radius = (0,_range__WEBPACK_IMPORTED_MODULE_1__.range)(startIndex, endIndex).reduce((accumulator, index_) => accumulator + radiusOfCurvatureAt(index_), 0); return radius / (endIndex - startIndex); } function pathIndexAtDistance(distances, distance) { // Adapted from `SplineTool::pathIndexAtDistance()` // let index = 0; // while (distances[index] <= distance) { // index++; // } const index = distances.findIndex(distance_ => distance_ > distance); if (index === -1 || index >= distances.length) { return distances.length - 1; } if (index <= 0) { return 0; } const d0 = distances[index - 1]; const d1 = distances[index]; // NOTE: Even though this doesn't feel like it matches the behaviour of the // function name, this is what the reference function does. return index * (d0 - distance) / (d0 - d1) + (index - 1) * (d1 - distance) / (d1 - d0); } /***/ }, /***/ 11681 /*!**************************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-distance-between-points.ts ***! \**************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateDistanceBetweenPoints: () => (/* binding */ calculateDistanceBetweenPoints) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function calculateDistanceBetweenPoints(start, end) { return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(start, end); } /***/ }, /***/ 67638 /*!*******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-distance-on-path.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateDistanceOnPath: () => (/* binding */ calculateDistanceOnPath) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./closest-path-index-to-position */ 86710); function calculateDistanceOnPath(path, position) { // Adapted from `CurvaturePointTool::updateAttachmentPosition()` const { minIndex } = (0,_closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__.closestPathIndexToPosition)(position, path); if (path.length <= 1 || minIndex === 0) { return 0; } let previousPoint = path[0]; let distance = 0; // This will not include the point closest to `position` for (const point of path.slice(1, minIndex)) { distance += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(previousPoint, point); previousPoint = point; } distance += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(previousPoint, position); return distance; } /***/ }, /***/ 88166 /*!****************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-path-distance.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculatePathDistance: () => (/* binding */ calculatePathDistance) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function calculatePathDistance(path, closed) { if (path.length <= 1) { return 0; } let previousPoint = path[0]; let distance = 0; for (const point of path.slice(1)) { distance += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(previousPoint, point); previousPoint = point; } if (closed) { distance += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(previousPoint, path[0]); } return distance; } /***/ }, /***/ 82403 /*!************************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-path-maximum-diameter.ts ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculatePathMaximumDiameter: () => (/* binding */ calculatePathMaximumDiameter) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function calculatePathMaximumDiameter(path) { let maxDiameter = 0; for (const pointA of path) { for (const pointB of path) { if (pointA !== pointB) { maxDiameter = Math.max(maxDiameter, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(pointA, pointB)); } } } return maxDiameter; } /***/ }, /***/ 78940 /*!*****************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-points-on-axis.ts ***! \*****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculatePointsOnAxis: () => (/* binding */ calculatePointsOnAxis) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _position__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../position */ 60174); function calculatePointsOnAxis(centroid, axisNormal, distance) { const start = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(start, centroid, axisNormal, distance / -2); const end = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(end, centroid, axisNormal, distance / 2); return [(0,_position__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(start), (0,_position__WEBPACK_IMPORTED_MODULE_1__.vec3ToPosition)(end)]; } /***/ }, /***/ 37917 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-radial-geometry.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateRadialGeometry: () => (/* binding */ calculateRadialGeometry) /* harmony export */ }); /** * Shared core logic for generating radial geometries. * Handles array allocation, index tracking, and trig caching. */ function calculateRadialGeometry(sides, trianglesPerSide, buildFaces) { // 3 vertices per triangle * 3 floats per vertex = 9 floats per triangle const totalFloats = sides * trianglesPerSide * 9; const vertices = new Float32Array(totalFloats); const normals = new Float32Array(totalFloats); const step = 2 * Math.PI / sides; let index = 0; let cos1 = 1; // Math.cos(0) let sin1 = 0; // Math.sin(0) const addVertex = (x, y, z, nx, ny, nz) => { vertices[index] = x; normals[index] = nx; index++; vertices[index] = y; normals[index] = ny; index++; vertices[index] = z; normals[index] = nz; index++; }; for (let index = 0; index < sides; index++) { const angle2 = (index + 1) * step; const cos2 = Math.cos(angle2); const sin2 = Math.sin(angle2); // Delegate face generation to the specific geometry builder buildFaces(addVertex, cos1, sin1, cos2, sin2); // Shift angles forward for the next segment cos1 = cos2; sin1 = sin2; } return { centroid: [0, 0, 0], indices: new Uint32Array(0), normals, vertices }; } /***/ }, /***/ 33904 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/geometry/calculate-spline-path.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateSplinePath: () => (/* binding */ calculateSplinePath) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _interpolation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../interpolation */ 28235); /* harmony import */ var _position__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../position */ 60174); /** * After providing a list of control points for a spline, * this will use cubic interpolation to return a full path. * @param points The control points for the spline * @param closed Whether the spline is closed or open * @returns A fully interpolated path */ // eslint-disable-next-line sonarjs/cyclomatic-complexity function calculateSplinePath(points, closed) { const MAX_INTERPOLATED_LENGTH = 500; const MIN_INTERPOLATE_LENGTH = 0.5; // NOTE: This was 10, but I don't see a noticable visual change - // keeping this lower will save some cycles const RESOLUTION = 5; if (points.length < 2) { return []; } const path = (0,_interpolation__WEBPACK_IMPORTED_MODULE_1__.cubicInterpolator)(points.map(p => [...p]), { isPeriodic: closed }); // Calculate number of interpolated points for each segment const numberInterpolation = []; let totalLength = 0; const numberSegments = points.length - (closed ? 0 : 1); for (let index = 0; index < numberSegments; index++) { let segLength = 0; let aVertex = path(index); let last = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(aVertex[0], aVertex[1], aVertex[2]); for (let index_ = 1; index_ < RESOLUTION; index_++) { aVertex = path(index + index_ / (RESOLUTION - 1)); const current = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(aVertex[0], aVertex[1], aVertex[2]); segLength += gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(last, current); last = current; } totalLength += segLength; numberInterpolation.push(Math.ceil(segLength / MIN_INTERPOLATE_LENGTH)); } // Apply maximum number of points if (totalLength > MAX_INTERPOLATED_LENGTH) { for (let index = 0; index < numberInterpolation.length; index++) { numberInterpolation[index] = Math.floor(MAX_INTERPOLATED_LENGTH / totalLength * (numberInterpolation[index] ?? 1)); } } let k = 0; const vertices = []; for (const n of numberInterpolation) { const dL = 1 / Math.max(n - 1, 1); for (let index = 0; index < n; index++) { const vertex = path(k + index * dL); // Skip duplicate points const previous = vertices.at(-1); if (!previous || !gl_matrix__WEBPACK_IMPORTED_MODULE_0__.equals(vertex, previous)) { vertices.push(vertex); } } k++; } return vertices.map(vertex => (0,_position__WEBPACK_IMPORTED_MODULE_2__.vec3ToPosition)(vertex)); } /***/ }, /***/ 86710 /*!***********************************************************************!*\ !*** ./libs/utils/src/lib/geometry/closest-path-index-to-position.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestPathIndexToPosition: () => (/* binding */ closestPathIndexToPosition) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** * After providing a position and the path of a spline, * this will return a list of distances between each path point and the provided position, * as well as the index of the shortest distance. * @param pos The position to measure against * @param path The list of positions which make up a spline's path * @returns A list of the distances between each point and `pos`, as well as the index of the closest point */ function closestPathIndexToPosition(pos, path) { // Adapted from `SplineTool::closestPathIndexToPoint()` const v = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(pos[0], pos[1], pos[2]); const distances = path.map(pt => gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(v, pt)); let minIndex = 0; let minValue = Infinity; for (const [index, distance] of distances.entries()) { if (distance < minValue) { minIndex = index; minValue = distance; } } return { distances, minIndex }; } /***/ }, /***/ 40487 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/closest-path-point-to-ray.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestPathPointToRay: () => (/* binding */ closestPathPointToRay) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** * The path point nearest a pick ray, for turning a click on a rendered path into a * position along it. Samples points rather than segments: paths here are dense enough * that the nearest sample is within a sample spacing of the true nearest point. */ function closestPathPointToRay(path, ray) { const origin = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...ray.origin); const direction = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(...ray.direction); const lengthSquared = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.squaredLength(direction); if (path.length === 0 || lengthSquared < 1e-12) return path[0]; const onRay = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); const offset = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); let closest; let best = Number.POSITIVE_INFINITY; for (const point of path) { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(offset, point, origin); // Behind the eye is never picked, so the ray is clamped to its forward half. const t = Math.max(0, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(offset, direction) / lengthSquared); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(onRay, origin, direction, t); const distance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.squaredDistance(point, onRay); if (distance < best) { best = distance; closest = point; } } return closest; } /***/ }, /***/ 94067 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/closest-point-to-triangle.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestPointToTriangle: () => (/* binding */ closestPointToTriangle) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); // Cache some vec3s - because `closestPointToTriangle` gets called a lot, // it would spend a lot of time reallocating vec3s otherwise const CPTT_VECS = [gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create()]; /** * Projects the provided point onto the triangle. * If the projection is within the triangle, it will return the point of projection. * If not, it will also check the edges for a closer projection point to return. */ function closestPointToTriangle(point, p0, p1, p2) { // Compute triangle plane const edge1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[0], p1, p0); const edge2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[1], p2, p1); const edge3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[2], p0, p2); const normal = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(CPTT_VECS[3], edge1, edge2); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(normal, normal); // Project point onto the plane const toP = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[4], point, p0); const planeDistance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(toP, normal); const projected = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scaleAndAdd(CPTT_VECS[5], point, normal, -planeDistance); // Test if projected point is inside triangle using barycentric coords const vp0 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[6], projected, p0); const vp1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[7], projected, p1); const vp2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTT_VECS[8], projected, p2); const c0 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(CPTT_VECS[9], edge1, vp0); const c1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(CPTT_VECS[10], edge2, vp1); const c2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.cross(CPTT_VECS[11], edge3, vp2); const inside = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(c0, normal) >= 0 && gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(c1, normal) >= 0 && gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(c2, normal) >= 0; if (inside) return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.clone(projected); // Otherwise fall back to closest point on the 3 edges const candidates = [closestPointToLine(point, p0, p1), closestPointToLine(point, p1, p2), closestPointToLine(point, p2, p0)]; // eslint-disable-next-line unicorn/no-array-reduce return candidates.reduce((best, current) => gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(point, best) < gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(point, current) ? best : current, candidates[0]); } const CPTL_VECS = [gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create()]; function closestPointToLine(point, p0, p1) { const n = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTL_VECS[0], p0, p1); const distance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(n); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n, n); const pCopy = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(CPTL_VECS[1], point, p1); const scale = Math.max(0, Math.min(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(pCopy, n), distance)); const result = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(CPTL_VECS[2], n, scale); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(result, result, p1); return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.clone(result); } /***/ }, /***/ 68853 /*!*********************************************************************!*\ !*** ./libs/utils/src/lib/geometry/closest-points-between-paths.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ closestPointsBetweenPaths: () => (/* binding */ closestPointsBetweenPaths) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _position__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../position */ 60174); /** * Given two paths, it returns the point on each path that is closest to the opposite path. * @param path1 * @param path2 */ function closestPointsBetweenPaths(path1, path2) { let out = [_position__WEBPACK_IMPORTED_MODULE_1__.ORIGIN, _position__WEBPACK_IMPORTED_MODULE_1__.ORIGIN]; let minDistance = Infinity; for (const point1 of path1) { for (const point2 of path2) { const newDistance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.distance(point1, point2); if (newDistance < minDistance) { minDistance = newDistance; out = [point1, point2]; } } } return out; } /***/ }, /***/ 16147 /*!****************************************************!*\ !*** ./libs/utils/src/lib/geometry/convex-hull.ts ***! \****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ computeConvexHull: () => (/* binding */ computeConvexHull) /* harmony export */ }); /* harmony import */ var quickhull3d__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! quickhull3d */ 28943); /* harmony import */ var _aabb__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./aabb */ 28522); /** * Convex hull of a triangle-soup vertex buffer. * * The smallest convex polygon that contains every input point. * For Object3D picking we use the hull as a "solid" proxy for the visible * mesh. It bounds the mesh and, unlike the mesh, has no holes, so a click * ray that passes through a hole in the visible geometry still hits the * proxy. For convex inputs (Cylinder) the hull equals the mesh. * For inputs with bores (HollowCylinder, STL) the hull fills the * bore, which is the property the click-through-bore picking depends on. * * */ function computeConvexHull(soup, weldEpsilon = 1e-5) { const welded = weldVertices(soup, weldEpsilon); const faces = (0,quickhull3d__WEBPACK_IMPORTED_MODULE_0__["default"])(welded); // Reindex hull faces to a dense vertex array (only vertices used by the hull). const remap = new Map(); const hullVertices = []; const indexBuffer = []; for (const face of faces) { for (const index of face) { let mapped = remap.get(index); if (mapped === undefined) { const v = welded[index]; if (!v) continue; mapped = hullVertices.length; remap.set(index, mapped); hullVertices.push(v); } indexBuffer.push(mapped); } } const vertices = new Float32Array(hullVertices.length * 3); for (const [index, [x, y, z]] of hullVertices.entries()) { vertices[index * 3] = x; vertices[index * 3 + 1] = y; vertices[index * 3 + 2] = z; } return { bounds: (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.aabbFromVertices)(vertices), indices: new Uint32Array(indexBuffer), vertices }; } /** Dedupes vertices by quantizing each coordinate to epsilon and keeping the first. */ function weldVertices(soup, epsilon) { const scale = 1 / epsilon; const seen = new Map(); const welded = []; for (let index = 0; index < soup.length; index += 3) { const x = soup[index] ?? 0; const y = soup[index + 1] ?? 0; const z = soup[index + 2] ?? 0; const key = `${Math.round(x * scale)}|${Math.round(y * scale)}|${Math.round(z * scale)}`; if (!seen.has(key)) { seen.set(key, welded.length); welded.push([x, y, z]); } } return welded; } /***/ }, /***/ 94815 /*!**********************************************************!*\ !*** ./libs/utils/src/lib/geometry/cylinder-geometry.ts ***! \**********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ calculateCylinderGeometry: () => (/* binding */ calculateCylinderGeometry), /* harmony export */ calculateHollowCylinderGeometry: () => (/* binding */ calculateHollowCylinderGeometry) /* harmony export */ }); /* harmony import */ var _calculate_radial_geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./calculate-radial-geometry */ 37917); function calculateCylinderGeometry(radius, height, sides) { const halfH = height / 2; // A solid cylinder has 4 triangles per side segment return (0,_calculate_radial_geometry__WEBPACK_IMPORTED_MODULE_0__.calculateRadialGeometry)(sides, 4, (addVertex, cos1, sin1, cos2, sin2) => { const x1 = radius * cos1, z1 = radius * sin1; const x2 = radius * cos2, z2 = radius * sin2; // Top cap addVertex(0, halfH, 0, 0, 1, 0); addVertex(x2, halfH, z2, 0, 1, 0); addVertex(x1, halfH, z1, 0, 1, 0); // Outer side addVertex(x1, halfH, z1, cos1, 0, sin1); addVertex(x2, halfH, z2, cos2, 0, sin2); addVertex(x1, -halfH, z1, cos1, 0, sin1); addVertex(x2, halfH, z2, cos2, 0, sin2); addVertex(x2, -halfH, z2, cos2, 0, sin2); addVertex(x1, -halfH, z1, cos1, 0, sin1); // Bottom cap addVertex(0, -halfH, 0, 0, -1, 0); addVertex(x1, -halfH, z1, 0, -1, 0); addVertex(x2, -halfH, z2, 0, -1, 0); }); } function calculateHollowCylinderGeometry(innerRadius, outerRadius, height, sides) { const halfH = height / 2; // A hollow cylinder has 8 triangles per side segment return (0,_calculate_radial_geometry__WEBPACK_IMPORTED_MODULE_0__.calculateRadialGeometry)(sides, 8, (addVertex, cos1, sin1, cos2, sin2) => { const inX1 = innerRadius * cos1, inZ1 = innerRadius * sin1; const outX1 = outerRadius * cos1, outZ1 = outerRadius * sin1; const inX2 = innerRadius * cos2, inZ2 = innerRadius * sin2; const outX2 = outerRadius * cos2, outZ2 = outerRadius * sin2; // Top face addVertex(inX1, halfH, inZ1, 0, 1, 0); addVertex(outX2, halfH, outZ2, 0, 1, 0); addVertex(outX1, halfH, outZ1, 0, 1, 0); addVertex(inX1, halfH, inZ1, 0, 1, 0); addVertex(inX2, halfH, inZ2, 0, 1, 0); addVertex(outX2, halfH, outZ2, 0, 1, 0); // Outer side addVertex(outX1, halfH, outZ1, cos1, 0, sin1); addVertex(outX2, -halfH, outZ2, cos2, 0, sin2); addVertex(outX1, -halfH, outZ1, cos1, 0, sin1); addVertex(outX1, halfH, outZ1, cos1, 0, sin1); addVertex(outX2, halfH, outZ2, cos2, 0, sin2); addVertex(outX2, -halfH, outZ2, cos2, 0, sin2); // Bottom face addVertex(inX1, -halfH, inZ1, 0, -1, 0); addVertex(outX1, -halfH, outZ1, 0, -1, 0); addVertex(outX2, -halfH, outZ2, 0, -1, 0); addVertex(inX1, -halfH, inZ1, 0, -1, 0); addVertex(outX2, -halfH, outZ2, 0, -1, 0); addVertex(inX2, -halfH, inZ2, 0, -1, 0); // Inner side addVertex(inX1, halfH, inZ1, -cos1, 0, -sin1); addVertex(inX1, -halfH, inZ1, -cos1, 0, -sin1); addVertex(inX2, -halfH, inZ2, -cos2, 0, -sin2); addVertex(inX1, halfH, inZ1, -cos1, 0, -sin1); addVertex(inX2, -halfH, inZ2, -cos2, 0, -sin2); addVertex(inX2, halfH, inZ2, -cos2, 0, -sin2); }); } /***/ }, /***/ 2096 /*!*********************************************************!*\ !*** ./libs/utils/src/lib/geometry/declutter-labels.ts ***! \*********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ declutterLabels: () => (/* binding */ declutterLabels) /* harmony export */ }); const DEFAULT_MAX_ITERATIONS = 50; const DEFAULT_VERTICAL_STEP = 2; function boxesOverlap(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; } /** Pushes two overlapping boxes apart vertically, the lower one down and the upper one up. */ function separate(a, b, verticalStep) { if (a.y <= b.y) { a.y -= verticalStep; b.y += verticalStep; } else { a.y += verticalStep; b.y -= verticalStep; } } /** One pass over every pair, separating any that overlap. Returns whether anything moved. */ function separateOverlappingPairs(placements, verticalStep) { let moved = false; for (let index = 0; index < placements.length; index++) { for (let index_ = index + 1; index_ < placements.length; index_++) { const a = placements[index]; const b = placements[index_]; if (!boxesOverlap(a, b)) continue; separate(a, b, verticalStep); moved = true; } } return moved; } /** * Nudges overlapping label boxes apart vertically until none overlap (or the iteration * budget runs out). Each label starts at its own anchor (e.g. offset from a graph point) and * is only ever moved along Y, so labels stay next to the point they belong to horizontally. */ function declutterLabels(boxes, options) { const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS; const verticalStep = options?.verticalStep ?? DEFAULT_VERTICAL_STEP; const placements = boxes.map(box => ({ height: box.height, id: box.id, width: box.width, x: box.anchorX, y: box.anchorY })); for (let iteration = 0; iteration < maxIterations; iteration++) { if (!separateOverlappingPairs(placements, verticalStep)) break; } return placements.map(({ id, x, y }) => ({ id, x, y })); } /***/ }, /***/ 99175 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/geometry/get-point-at-distance.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getPointAtDistance: () => (/* binding */ getPointAtDistance) /* harmony export */ }); function getPointAtDistance(path, distance) { const length = path.length; const index = Math.max(0, Math.floor(length * Math.min(1, distance)) - 1); return path[index]; } /***/ }, /***/ 63134 /*!**********************************************!*\ !*** ./libs/utils/src/lib/geometry/index.ts ***! \**********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA: () => (/* reexport safe */ _annotation_plane_fade__WEBPACK_IMPORTED_MODULE_2__.ANNOTATION_SELECTED_OUT_OF_PLANE_ALPHA), /* harmony export */ ANNOTATION_VISIBLE_DISTANCE_MM: () => (/* reexport safe */ _annotation_plane_fade__WEBPACK_IMPORTED_MODULE_2__.ANNOTATION_VISIBLE_DISTANCE_MM), /* harmony export */ aabbCentreDepth: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbCentreDepth), /* harmony export */ aabbFromVec3s: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbFromVec3s), /* harmony export */ aabbFromVertices: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbFromVertices), /* harmony export */ aabbOverlap: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbOverlap), /* harmony export */ aabbRayIntersect: () => (/* reexport safe */ _ray__WEBPACK_IMPORTED_MODULE_28__.aabbRayIntersect), /* harmony export */ aabbToVec3s: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbToVec3s), /* harmony export */ aabbVolume: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.aabbVolume), /* harmony export */ addPointToSpline: () => (/* reexport safe */ _add_point_to_spline__WEBPACK_IMPORTED_MODULE_0__.addPointToSpline), /* harmony export */ alignAxisOfSymmetryToView: () => (/* reexport safe */ _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__.alignAxisOfSymmetryToView), /* harmony export */ angulationFromOrientation: () => (/* reexport safe */ _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__.angulationFromOrientation), /* harmony export */ angulationToVector: () => (/* reexport safe */ _angulation_to_vector__WEBPACK_IMPORTED_MODULE_1__.angulationToVector), /* harmony export */ annotationPointInBand: () => (/* reexport safe */ _annotation_plane_fade__WEBPACK_IMPORTED_MODULE_2__.annotationPointInBand), /* harmony export */ autoAlignAxis: () => (/* reexport safe */ _axis_alignment__WEBPACK_IMPORTED_MODULE_3__.autoAlignAxis), /* harmony export */ buildObject3dTransform: () => (/* reexport safe */ _object3d_transform__WEBPACK_IMPORTED_MODULE_32__.buildObject3dTransform), /* harmony export */ calculateAngleBetweenPoints: () => (/* reexport safe */ _calculate_angle_between_points__WEBPACK_IMPORTED_MODULE_4__.calculateAngleBetweenPoints), /* harmony export */ calculateClosedSplineArea: () => (/* reexport safe */ _calculate_closed_spline_area__WEBPACK_IMPORTED_MODULE_5__.calculateClosedSplineArea), /* harmony export */ calculateClosedSplineBestFitNormal: () => (/* reexport safe */ _calculate_closed_spline_best_fit_normal__WEBPACK_IMPORTED_MODULE_6__.calculateClosedSplineBestFitNormal), /* harmony export */ calculateClosedSplineHeight: () => (/* reexport safe */ _calculate_closed_spline_height__WEBPACK_IMPORTED_MODULE_7__.calculateClosedSplineHeight), /* harmony export */ calculateCurvatureRadius: () => (/* reexport safe */ _calculate_curvature_radius__WEBPACK_IMPORTED_MODULE_9__.calculateCurvatureRadius), /* harmony export */ calculateCylinderGeometry: () => (/* reexport safe */ _cylinder_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateCylinderGeometry), /* harmony export */ calculateDistanceBetweenPoints: () => (/* reexport safe */ _calculate_distance_between_points__WEBPACK_IMPORTED_MODULE_10__.calculateDistanceBetweenPoints), /* harmony export */ calculateDistanceOnPath: () => (/* reexport safe */ _calculate_distance_on_path__WEBPACK_IMPORTED_MODULE_11__.calculateDistanceOnPath), /* harmony export */ calculateHollowCylinderGeometry: () => (/* reexport safe */ _cylinder_geometry__WEBPACK_IMPORTED_MODULE_18__.calculateHollowCylinderGeometry), /* harmony export */ calculatePathDistance: () => (/* reexport safe */ _calculate_path_distance__WEBPACK_IMPORTED_MODULE_12__.calculatePathDistance), /* harmony export */ calculatePathMaximumDiameter: () => (/* reexport safe */ _calculate_path_maximum_diameter__WEBPACK_IMPORTED_MODULE_13__.calculatePathMaximumDiameter), /* harmony export */ calculatePointsOnAxis: () => (/* reexport safe */ _calculate_points_on_axis__WEBPACK_IMPORTED_MODULE_14__.calculatePointsOnAxis), /* harmony export */ calculateSplinePath: () => (/* reexport safe */ _calculate_spline_path__WEBPACK_IMPORTED_MODULE_15__.calculateSplinePath), /* harmony export */ closestPathPointToRay: () => (/* reexport safe */ _closest_path_point_to_ray__WEBPACK_IMPORTED_MODULE_16__.closestPathPointToRay), /* harmony export */ closestPointsBetweenPaths: () => (/* reexport safe */ _closest_points_between_paths__WEBPACK_IMPORTED_MODULE_17__.closestPointsBetweenPaths), /* harmony export */ declutterLabels: () => (/* reexport safe */ _declutter_labels__WEBPACK_IMPORTED_MODULE_19__.declutterLabels), /* harmony export */ flipAxisOfSymmetry: () => (/* reexport safe */ _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__.flipAxisOfSymmetry), /* harmony export */ getPointAtDistance: () => (/* reexport safe */ _get_point_at_distance__WEBPACK_IMPORTED_MODULE_20__.getPointAtDistance), /* harmony export */ minDistanceToAABB: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.minDistanceToAABB), /* harmony export */ mostDistinctAxis: () => (/* reexport safe */ _axis_alignment__WEBPACK_IMPORTED_MODULE_3__.mostDistinctAxis), /* harmony export */ object3dSymmetryAxis: () => (/* reexport safe */ _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__.object3dSymmetryAxis), /* harmony export */ orientationFromAngulation: () => (/* reexport safe */ _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__.orientationFromAngulation), /* harmony export */ parseSTL: () => (/* reexport safe */ _stl_parser__WEBPACK_IMPORTED_MODULE_33__.parseSTL), /* harmony export */ projectPointOnGeometry: () => (/* reexport safe */ _project_point_on_geometry__WEBPACK_IMPORTED_MODULE_21__.projectPointOnGeometry), /* harmony export */ projectPointOnOctree: () => (/* reexport safe */ _project_point_on_octree__WEBPACK_IMPORTED_MODULE_22__.projectPointOnOctree), /* harmony export */ projectPointOnPlane: () => (/* reexport safe */ _project_point_on_plane__WEBPACK_IMPORTED_MODULE_23__.projectPointOnPlane), /* harmony export */ projectedAabbArea: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.projectedAabbArea), /* harmony export */ projectedAabbBounds2d: () => (/* reexport safe */ _aabb__WEBPACK_IMPORTED_MODULE_27__.projectedAabbBounds2d), /* harmony export */ sCurvePointOnPath: () => (/* reexport safe */ _s_curve_point_on_path__WEBPACK_IMPORTED_MODULE_29__.sCurvePointOnPath), /* harmony export */ signedDistanceToPlane: () => (/* reexport safe */ _annotation_plane_fade__WEBPACK_IMPORTED_MODULE_2__.signedDistanceToPlane), /* harmony export */ silhouetteContainsClick: () => (/* reexport safe */ _silhouette__WEBPACK_IMPORTED_MODULE_30__.silhouetteContainsClick), /* harmony export */ snapPositionToAngle: () => (/* reexport safe */ _snap_position_to_angle__WEBPACK_IMPORTED_MODULE_24__.snapPositionToAngle), /* harmony export */ snapPositionToLine: () => (/* reexport safe */ _snap_position_to_line__WEBPACK_IMPORTED_MODULE_25__.snapPositionToLine), /* harmony export */ snapPositionToSpline: () => (/* reexport safe */ _snap_position_to_spline__WEBPACK_IMPORTED_MODULE_26__.snapPositionToSpline), /* harmony export */ transformRayToLocal: () => (/* reexport safe */ _ray__WEBPACK_IMPORTED_MODULE_28__.transformRayToLocal), /* harmony export */ validateViewportAngle: () => (/* reexport safe */ _calculate_coronal_angle__WEBPACK_IMPORTED_MODULE_8__.validateViewportAngle), /* harmony export */ vectorToAngulation: () => (/* reexport safe */ _vector_to_angulation__WEBPACK_IMPORTED_MODULE_34__.vectorToAngulation) /* harmony export */ }); /* harmony import */ var _add_point_to_spline__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add-point-to-spline */ 66706); /* harmony import */ var _angulation_to_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./angulation-to-vector */ 69232); /* harmony import */ var _annotation_plane_fade__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./annotation-plane-fade */ 64469); /* harmony import */ var _axis_alignment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./axis-alignment */ 7921); /* harmony import */ var _calculate_angle_between_points__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./calculate-angle-between-points */ 25257); /* harmony import */ var _calculate_closed_spline_area__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./calculate-closed-spline-area */ 68555); /* harmony import */ var _calculate_closed_spline_best_fit_normal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./calculate-closed-spline-best-fit-normal */ 10840); /* harmony import */ var _calculate_closed_spline_height__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./calculate-closed-spline-height */ 44465); /* harmony import */ var _calculate_coronal_angle__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./calculate-coronal-angle */ 14445); /* harmony import */ var _calculate_curvature_radius__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./calculate-curvature-radius */ 91905); /* harmony import */ var _calculate_distance_between_points__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./calculate-distance-between-points */ 11681); /* harmony import */ var _calculate_distance_on_path__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./calculate-distance-on-path */ 67638); /* harmony import */ var _calculate_path_distance__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./calculate-path-distance */ 88166); /* harmony import */ var _calculate_path_maximum_diameter__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./calculate-path-maximum-diameter */ 82403); /* harmony import */ var _calculate_points_on_axis__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./calculate-points-on-axis */ 78940); /* harmony import */ var _calculate_spline_path__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./calculate-spline-path */ 33904); /* harmony import */ var _closest_path_point_to_ray__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./closest-path-point-to-ray */ 40487); /* harmony import */ var _closest_points_between_paths__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./closest-points-between-paths */ 68853); /* harmony import */ var _cylinder_geometry__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./cylinder-geometry */ 94815); /* harmony import */ var _declutter_labels__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./declutter-labels */ 2096); /* harmony import */ var _get_point_at_distance__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./get-point-at-distance */ 99175); /* harmony import */ var _project_point_on_geometry__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./project-point-on-geometry */ 78449); /* harmony import */ var _project_point_on_octree__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./project-point-on-octree */ 97167); /* harmony import */ var _project_point_on_plane__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./project-point-on-plane */ 46987); /* harmony import */ var _snap_position_to_angle__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./snap-position-to-angle */ 30528); /* harmony import */ var _snap_position_to_line__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./snap-position-to-line */ 95577); /* harmony import */ var _snap_position_to_spline__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./snap-position-to-spline */ 30530); /* harmony import */ var _aabb__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./aabb */ 28522); /* harmony import */ var _ray__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./ray */ 91498); /* harmony import */ var _s_curve_point_on_path__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./s-curve-point-on-path */ 38404); /* harmony import */ var _silhouette__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./silhouette */ 69177); /* harmony import */ var _object3d_orientation__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./object3d-orientation */ 88687); /* harmony import */ var _object3d_transform__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./object3d-transform */ 61081); /* harmony import */ var _stl_parser__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./stl-parser */ 1759); /* harmony import */ var _vector_to_angulation__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./vector-to-angulation */ 39844); /***/ }, /***/ 88687 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/geometry/object3d-orientation.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ alignAxisOfSymmetryToView: () => (/* binding */ alignAxisOfSymmetryToView), /* harmony export */ angulationFromOrientation: () => (/* binding */ angulationFromOrientation), /* harmony export */ flipAxisOfSymmetry: () => (/* binding */ flipAxisOfSymmetry), /* harmony export */ object3dSymmetryAxis: () => (/* binding */ object3dSymmetryAxis), /* harmony export */ orientationFromAngulation: () => (/* binding */ orientationFromAngulation) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 85648); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! gl-matrix */ 87396); const DEG_TO_RAD = Math.PI / 180; const RAD_TO_DEG = 180 / Math.PI; const clamp = (value, min, max) => Math.min(Math.max(value, min), max); /** Build the orientation quaternion for `R = Rz(rl) * Rx(-cc) * Ry(ax)`. */ function orientationFromAngulation({ ax, cc, rl }) { // Create one quaternion per axis. It builds a rotation of `angle` radians // about the given unit axis, so we convert each slider from degrees first. const qz = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), [0, 0, 1], rl * DEG_TO_RAD); const qx = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), [1, 0, 0], -cc * DEG_TO_RAD); // -cc: sign convention so the tilt goes the expected way const qy = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.setAxisAngle(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), [0, 1, 0], ax * DEG_TO_RAD); // Combine them. Multiplying quaternions chains their rotations, so this is // the single rotation equal to "do qy, then qx, then qz". const result = gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_2__.multiply(result, qz, qx); // qz * qx gl_matrix__WEBPACK_IMPORTED_MODULE_2__.multiply(result, result, qy); // qz * qx * qy // Floating-point math can drift the length away from 1, we renormalize gl_matrix__WEBPACK_IMPORTED_MODULE_2__.normalize(result, result); return [result[0], result[1], result[2], result[3]]; } /** * Decompose an orientation quaternion into ZXY angles (degrees). */ function angulationFromOrientation(orientation) { const m = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), orientation); // The cc angle shows up as one matrix entry equal to its sine, so a single asin recovers it. const beta = Math.asin(clamp(m[6], -1, 1)); // R[2][1] const cc = -beta * RAD_TO_DEG; // undo the -cc sign used when building the quaternion // The rl and ax don't sit in a single entry, so they're recovered from a pair // each. atan2 uses the sign of both arguments, giving the correct angle // across the full -180°..180° range. const rl = Math.atan2(-m[4], m[5]) * RAD_TO_DEG; // atan2(-R[0][1], R[1][1]) const ax = Math.atan2(-m[2], m[10]) * RAD_TO_DEG; // atan2(-R[2][0], R[2][2]) return { ax, cc, rl }; } function alignAxisOfSymmetryToView(axisOfSymmetryRotation, object, view) { const r = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.rotateX(r, r, view.cc * DEG_TO_RAD); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.rotateZ(r, r, -view.rl * DEG_TO_RAD); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.rotateZ(r, r, object.rl * DEG_TO_RAD); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.rotateX(r, r, -object.cc * DEG_TO_RAD); const result = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.multiply(result, r, Float32Array.from(axisOfSymmetryRotation)); return [...result]; } function flipAxisOfSymmetry(axisOfSymmetryRotation) { const flip = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.rotateX(flip, flip, Math.PI); const result = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.multiply(result, flip, Float32Array.from(axisOfSymmetryRotation)); return [...result]; } /** * World-space direction of an Object3D's axis of rotational symmetry. * * @param orientation Object3D orientation quaternion `[x, y, z, w]`. * @param axisOfSymmetryRotation Optional STL-only PCA alignment matrix. */ function object3dSymmetryAxis(orientation, axisOfSymmetryRotation) { const axis = gl_matrix__WEBPACK_IMPORTED_MODULE_3__.fromValues(0, 1, 0); if (axisOfSymmetryRotation) { const rotation = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromMat4(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), Float32Array.from(axisOfSymmetryRotation)); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.transformMat3(axis, axis, rotation); } gl_matrix__WEBPACK_IMPORTED_MODULE_3__.transformQuat(axis, axis, orientation); gl_matrix__WEBPACK_IMPORTED_MODULE_3__.normalize(axis, axis); return [axis[0], axis[1], axis[2]]; } /***/ }, /***/ 61081 /*!***********************************************************!*\ !*** ./libs/utils/src/lib/geometry/object3d-transform.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildObject3dTransform: () => (/* binding */ buildObject3dTransform) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var _tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/dtos */ 55492); /** 4x4 actor transform: T(pos)R(orient), plus A(axisOfSymmetry)T(-centroid) for STL. * Shared by the visible actor and the picking gate, do not reimplement inline. */ function buildObject3dTransform(annotation, centroid = [0, 0, 0]) { const rotation = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromQuat(rotation, annotation.orientation); const transform = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromTranslation(transform, annotation.position); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(transform, transform, rotation); if ((0,_tomoverse_dtos__WEBPACK_IMPORTED_MODULE_1__.annotationIsStl)(annotation)) { const axisOfSymmetry = Float32Array.from(annotation.axisOfSymmetryRotation); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(transform, transform, axisOfSymmetry); const [cx, cy, cz] = annotation.centerOfRotation ?? centroid; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.translate(transform, transform, [-cx, -cy, -cz]); } return transform; } /***/ }, /***/ 90702 /*!***********************************************!*\ !*** ./libs/utils/src/lib/geometry/octree.ts ***! \***********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildOctree: () => (/* binding */ buildOctree) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _aabb__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./aabb */ 28522); /* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Breaks down geometry into an octree-based BVH, which will allow us to * more efficiently do some projections / hit detection / etc. */ function buildOctree(geometry, maxDepth = 8, maxTrianglesPerLeaf = 16) { const triCount = geometry.vertices.length / 9; // NOTE: maxDepth doesn't really do what it should yet // Compute bounds of whole mesh const min = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(Infinity, Infinity, Infinity); const max = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(-Infinity, -Infinity, -Infinity); for (let index = 0; index < geometry.vertices.length; index += 3) { min[0] = Math.min(min[0], geometry.vertices[index]); min[1] = Math.min(min[1], geometry.vertices[index + 1]); min[2] = Math.min(min[2], geometry.vertices[index + 2]); max[0] = Math.max(max[0], geometry.vertices[index]); max[1] = Math.max(max[1], geometry.vertices[index + 1]); max[2] = Math.max(max[2], geometry.vertices[index + 2]); } const allIndices = Array.from({ length: triCount }, (_, index) => index); return buildNode(geometry, allIndices, min, max, maxDepth, maxTrianglesPerLeaf); } function buildNode(geometry, triangleIndices, min, max, depth, maxTrianglesPerLeaf) { const node = { bounds: (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.aabbFromVec3s)(min, max), triangleIndices: [] }; if (depth === 0 || triangleIndices.length <= maxTrianglesPerLeaf) { node.triangleIndices = triangleIndices; return node; } // Split at midpoint const mid = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues((min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2); // Define 8 child bounding boxes const childBounds = [[min[0], min[1], min[2], mid[0], mid[1], mid[2]], [mid[0], min[1], min[2], max[0], mid[1], mid[2]], [min[0], mid[1], min[2], mid[0], max[1], mid[2]], [mid[0], mid[1], min[2], max[0], max[1], mid[2]], [min[0], min[1], mid[2], mid[0], mid[1], max[2]], [mid[0], min[1], mid[2], max[0], mid[1], max[2]], [min[0], mid[1], mid[2], mid[0], max[1], max[2]], [mid[0], mid[1], mid[2], max[0], max[1], max[2]]]; // Assign each triangle to whichever children its AABB overlaps const childIndices = childBounds.map(() => []); for (const triIndex of triangleIndices) { const triMin = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(Infinity, Infinity, Infinity); const triMax = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(-Infinity, -Infinity, -Infinity); for (let v = 0; v < 3; v++) { const base = triIndex * 9 + v * 3; triMin[0] = Math.min(triMin[0], geometry.vertices[base]); triMin[1] = Math.min(triMin[1], geometry.vertices[base + 1]); triMin[2] = Math.min(triMin[2], geometry.vertices[base + 2]); triMax[0] = Math.max(triMax[0], geometry.vertices[base]); triMax[1] = Math.max(triMax[1], geometry.vertices[base + 1]); triMax[2] = Math.max(triMax[2], geometry.vertices[base + 2]); } const triBounds = (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.aabbFromVec3s)(triMin, triMax); for (let c = 0; c < 8; c++) { const bounds = childBounds[c]; if (!bounds) continue; if ((0,_aabb__WEBPACK_IMPORTED_MODULE_1__.aabbOverlap)(triBounds, bounds)) { childIndices[c]?.push(triIndex); } } } node.children = childBounds.map((bounds, c) => { const [min, max] = (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.aabbToVec3s)(bounds); return buildNode(geometry, childIndices[c], min, max, depth - 1, maxTrianglesPerLeaf); }); return node; } /***/ }, /***/ 78449 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/geometry/project-point-on-geometry.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectPointOnGeometry: () => (/* binding */ projectPointOnGeometry) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _closest_point_to_triangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./closest-point-to-triangle */ 94067); function projectPointOnGeometry(point, geometry) { let bestPoint = undefined; let bestDistance = Infinity; const triCount = geometry.vertices.length / 9; for (let index = 0; index < triCount; index++) { const index0 = index * 3 + 0; const index1 = index * 3 + 1; const index2 = index * 3 + 2; try { const p0 = pointFromVertices(geometry.vertices, index0); const p1 = pointFromVertices(geometry.vertices, index1); const p2 = pointFromVertices(geometry.vertices, index2); const closest = (0,_closest_point_to_triangle__WEBPACK_IMPORTED_MODULE_1__.closestPointToTriangle)(point, p0, p1, p2); const d = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(point, closest); if (d < bestDistance) { bestDistance = d; bestPoint = closest; } } catch (error) { console.warn('Failed to process triangle', error); continue; } } return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.clone(bestPoint ?? point); } function pointFromVertices(vertices, index) { const x = vertices[index * 3 + 0]; const y = vertices[index * 3 + 1]; const z = vertices[index * 3 + 2]; if (x === undefined || y === undefined || z === undefined) { throw new Error('Missing vertex data'); } return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(x, y, z); } /***/ }, /***/ 97167 /*!****************************************************************!*\ !*** ./libs/utils/src/lib/geometry/project-point-on-octree.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectPointOnOctree: () => (/* binding */ projectPointOnOctree) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _aabb__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./aabb */ 28522); /* harmony import */ var _closest_point_to_triangle__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./closest-point-to-triangle */ 94067); /* eslint-disable @typescript-eslint/no-non-null-assertion */ function projectPointOnOctree(point, geometry, octree) { const bestDistance = { value: Infinity }; const bestPoint = { value: undefined }; queryOctree(point, octree, geometry, bestDistance, bestPoint); return bestPoint.value; } function queryOctree(point, node, geometry, bestDistance, bestPoint) { // Prune if the closest possible point in this node's bounds // is already farther than our current best if ((0,_aabb__WEBPACK_IMPORTED_MODULE_1__.minDistanceToAABB)(point, node.bounds) >= bestDistance.value) { return; } if (node.children === undefined) { // Leaf — check triangles directly for (const triIndex of node.triangleIndices) { const base = triIndex * 9; const p0 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(geometry.vertices[base], geometry.vertices[base + 1], geometry.vertices[base + 2]); const p1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(geometry.vertices[base + 3], geometry.vertices[base + 4], geometry.vertices[base + 5]); const p2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(geometry.vertices[base + 6], geometry.vertices[base + 7], geometry.vertices[base + 8]); const closest = (0,_closest_point_to_triangle__WEBPACK_IMPORTED_MODULE_2__.closestPointToTriangle)(point, p0, p1, p2); const d = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dist(point, closest); if (d < bestDistance.value) { bestDistance.value = d; bestPoint.value = closest; } } return; } // Recurse into children, visiting closer ones first const sortedChildren = node.children?.toSorted((a, b) => (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.minDistanceToAABB)(point, a.bounds) - (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.minDistanceToAABB)(point, b.bounds)) ?? []; for (const child of sortedChildren) { queryOctree(point, child, geometry, bestDistance, bestPoint); } } /***/ }, /***/ 46987 /*!***************************************************************!*\ !*** ./libs/utils/src/lib/geometry/project-point-on-plane.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ projectPointOnPlane: () => (/* binding */ projectPointOnPlane) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** * Project a point onto the plane that is created by the provided normal + centroid. * @param point * @param normal * @param centroid * @returns */ function projectPointOnPlane(point, normal, centroid) { const offset = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), point, centroid); const projection = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), normal, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(offset, normal)); return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), point, projection); } /***/ }, /***/ 91498 /*!********************************************!*\ !*** ./libs/utils/src/lib/geometry/ray.ts ***! \********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ aabbRayIntersect: () => (/* binding */ aabbRayIntersect), /* harmony export */ transformRayToLocal: () => (/* binding */ transformRayToLocal) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 95329); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 87396); // Ray primitives: parametric line in world space and the helpers that // transform rays between frames and intersect them with axis-aligned boxes. const EPSILON = 1e-7; /** Ray-vs-AABB slab test. Returns the t-range inside the box, or undefined on miss. */ function aabbRayIntersect(ray, bounds) { const [ox, oy, oz] = ray.origin; const [dx, dy, dz] = ray.direction; const [minX, minY, minZ, maxX, maxY, maxZ] = bounds; const slabs = [{ d: dx, max: maxX, min: minX, o: ox }, { d: dy, max: maxY, min: minY, o: oy }, { d: dz, max: maxZ, min: minZ, o: oz }]; let tNear = -Infinity; let tFar = Infinity; for (const { d, max, min, o } of slabs) { if (d > -EPSILON && d < EPSILON) { if (o < min || o > max) return undefined; continue; } const invD = 1 / d; let t1 = (min - o) * invD; let t2 = (max - o) * invD; if (t1 > t2) [t1, t2] = [t2, t1]; if (t1 > tNear) tNear = t1; if (t2 < tFar) tFar = t2; if (tNear > tFar) return undefined; } return { tEnter: tNear, tExit: tFar }; } const inverseScratch = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); const originScratch = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); const tipScratch = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(); /** Transforms a world ray into a local frame via mat4.invert(userMatrix). * Origin and tip are inverted separately to preserve direction length. */ function transformRayToLocal(ray, userMatrix) { if (!gl_matrix__WEBPACK_IMPORTED_MODULE_0__.invert(inverseScratch, userMatrix)) return undefined; gl_matrix__WEBPACK_IMPORTED_MODULE_1__.set(originScratch, ray.origin[0], ray.origin[1], ray.origin[2]); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat4(originScratch, originScratch, inverseScratch); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.set(tipScratch, ray.origin[0] + ray.direction[0], ray.origin[1] + ray.direction[1], ray.origin[2] + ray.direction[2]); gl_matrix__WEBPACK_IMPORTED_MODULE_1__.transformMat4(tipScratch, tipScratch, inverseScratch); return { direction: [tipScratch[0] - originScratch[0], tipScratch[1] - originScratch[1], tipScratch[2] - originScratch[2]], origin: [originScratch[0], originScratch[1], originScratch[2]] }; } /***/ }, /***/ 38404 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/geometry/s-curve-point-on-path.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ sCurvePointOnPath: () => (/* binding */ sCurvePointOnPath) /* harmony export */ }); /* harmony import */ var _angles__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../angles */ 13413); function sCurvePointOnPath(rl, angle) { rl = (0,_angles__WEBPACK_IMPORTED_MODULE_0__.deg2rad)(rl); const angleRl = (0,_angles__WEBPACK_IMPORTED_MODULE_0__.deg2rad)(angle.rl); const angleCc = (0,_angles__WEBPACK_IMPORTED_MODULE_0__.deg2rad)(angle.cc); return (0,_angles__WEBPACK_IMPORTED_MODULE_0__.rad2deg)(-Math.atan(Math.cos(rl - angleRl) / Math.tan(angleCc))); } /***/ }, /***/ 69177 /*!***************************************************!*\ !*** ./libs/utils/src/lib/geometry/silhouette.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ silhouetteContainsClick: () => (/* binding */ silhouetteContainsClick) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _aabb__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./aabb */ 28522); // Screen-space silhouette test: /** True if the click pixel lies inside the shape's 2D screen-space silhouette * * Given a shape's bounds and vertex buffer, * project them through the same camera the user sees and check whether a * click pixel falls inside the resulting 2D footprint. Used by the picking * gate when the hardware selector misses.*/ // eslint-disable-next-line sonarjs/cyclomatic-complexity -- straight-line min/max tracking on a hot path; extracting helpers would just rebuild it. function silhouetteContainsClick(shape, userMatrix, project, click) { // Fast-reject via 8 AABB corners. const cornerRect = (0,_aabb__WEBPACK_IMPORTED_MODULE_1__.projectedAabbBounds2d)(shape.bounds, userMatrix, project); if (!cornerRect) return false; if (click[0] < cornerRect.minX || click[0] > cornerRect.maxX || click[1] < cornerRect.minY || click[1] > cornerRect.maxY) { return false; } // Tighten by projecting every vertex, rejects clicks in the AABB-vs-hull halo. let minX = Infinity, minY = Infinity; let maxX = -Infinity, maxY = -Infinity; const local = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); const world = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); for (let index = 0; index < shape.vertices.length; index += 3) { local[0] = shape.vertices[index] ?? 0; local[1] = shape.vertices[index + 1] ?? 0; local[2] = shape.vertices[index + 2] ?? 0; gl_matrix__WEBPACK_IMPORTED_MODULE_0__.transformMat4(world, local, userMatrix); const p = project(world); if (!p) continue; if (p[0] < minX) minX = p[0]; if (p[0] > maxX) maxX = p[0]; if (p[1] < minY) minY = p[1]; if (p[1] > maxY) maxY = p[1]; } if (minX === Infinity) return false; return click[0] >= minX && click[0] <= maxX && click[1] >= minY && click[1] <= maxY; } /***/ }, /***/ 30528 /*!***************************************************************!*\ !*** ./libs/utils/src/lib/geometry/snap-position-to-angle.ts ***! \***************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ snapPositionToAngle: () => (/* binding */ snapPositionToAngle) /* harmony export */ }); /* harmony import */ var _calculate_spline_path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./calculate-spline-path */ 33904); /* harmony import */ var _snap_position_to_spline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./snap-position-to-spline */ 30530); /** * After providing a position and the start/middle/end positions of an angle, * this will return a point on the angle that is closest to the original position. * @param pos The initial position * @param start The starting point of the angle to snap to * @param middle The middle point of the angle to snap to * @param end The ending point of the angle to snap to * @returns The updated position which is on the line. */ function snapPositionToAngle(pos, start, middle, end) { const path = [...(0,_calculate_spline_path__WEBPACK_IMPORTED_MODULE_0__.calculateSplinePath)([start, middle], false), ...(0,_calculate_spline_path__WEBPACK_IMPORTED_MODULE_0__.calculateSplinePath)([middle, end], false)]; return (0,_snap_position_to_spline__WEBPACK_IMPORTED_MODULE_1__.snapPositionToSpline)(pos, path); } /***/ }, /***/ 95577 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/geometry/snap-position-to-line.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ snapPositionToLine: () => (/* binding */ snapPositionToLine) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /** * After providing a position and the start/end positions of a line, * this will return a point on the line that is closest to the original position. * @param pos The initial position * @param lineStart The starting point of the line to snap to * @param lineEnd The ending point of the line to snap to * @returns The updated position which is on the line. */ function snapPositionToLine(pos, lineStart, lineEnd) { // Adapted from `DistanceTool::projectPointOnTool()` const v = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(pos[0], pos[1], pos[2]); const point1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(lineStart[0], lineStart[1], lineStart[2]); const point2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(lineEnd[0], lineEnd[1], lineEnd[2]); const n = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(n, point1, point2); const distance = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.length(n); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n, n); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(v, v, point2); const scale = Math.max(0, Math.min(distance, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(v, n))); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(v, n, scale); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(v, v, point2); return [v[0], v[1], v[2]]; } /***/ }, /***/ 30530 /*!****************************************************************!*\ !*** ./libs/utils/src/lib/geometry/snap-position-to-spline.ts ***! \****************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ snapPositionToSpline: () => (/* binding */ snapPositionToSpline) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./closest-path-index-to-position */ 86710); /** * After providing a position and the path of a spline, * this will return a point on the spline that is closest to the original position. * @param pos The initial position * @param path The list of positions which make up a spline's path * @returns The updated position which is on the spline's path. */ function snapPositionToSpline(pos, path) { // Adapted from `SplineTool::projectPointOnTool()` const v = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(pos[0], pos[1], pos[2]); const { distances, minIndex } = (0,_closest_path_index_to_position__WEBPACK_IMPORTED_MODULE_1__.closestPathIndexToPosition)(pos, path); const pathCount = path.length; // If at one of the ends of the path, we can return that if (minIndex === 0 || minIndex === pathCount - 1) { return path[minIndex]; } const secondMinIndex = (distances[(minIndex + 1) % pathCount] ?? 0) > (distances[(minIndex - 1) % pathCount] ?? 0) ? minIndex - 1 : minIndex + 1; const minPos = path[minIndex]; const minPos2 = path[secondMinIndex]; const point0 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(minPos[0], minPos[1], minPos[2]); const point1 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(minPos2[0], minPos2[1], minPos2[2]); const n = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(n, point1, point0); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.normalize(n, n); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.sub(v, v, point0); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(v, n, gl_matrix__WEBPACK_IMPORTED_MODULE_0__.dot(v, n)); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(v, v, point0); return [v[0], v[1], v[2]]; } /***/ }, /***/ 1759 /*!***************************************************!*\ !*** ./libs/utils/src/lib/geometry/stl-parser.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ parseSTL: () => (/* binding */ parseSTL) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); const HEADER_SIZE = 80; const TRI_COUNT_SIZE = 4; const TRIANGLE_SIZE = 50; const VERTEX_OFFSET = 12; // Bytes from start of triangle to the first vertex function isBinary(buffer) { if (!buffer || buffer.byteLength < HEADER_SIZE + TRI_COUNT_SIZE) { return false; } const numberTri = new DataView(buffer).getUint32(HEADER_SIZE, true); return buffer.byteLength === HEADER_SIZE + TRI_COUNT_SIZE + numberTri * TRIANGLE_SIZE; } function readBinarySTL(buffer) { const dv = new DataView(buffer); const numberTri = dv.getUint32(HEADER_SIZE, true); const totalElements = numberTri * 9; const vertices = new Float32Array(totalElements); const normals = new Float32Array(totalElements); let offset = 0; for (let index = 0; index < numberTri; index++) { const triOffset = HEADER_SIZE + TRI_COUNT_SIZE + index * TRIANGLE_SIZE; const nx = dv.getFloat32(triOffset, true); const ny = dv.getFloat32(triOffset + 4, true); const nz = dv.getFloat32(triOffset + 8, true); for (let v = 0; v < 3; v++) { const vertBase = triOffset + VERTEX_OFFSET + v * 12; vertices[offset] = dv.getFloat32(vertBase, true); normals[offset++] = nx; vertices[offset] = dv.getFloat32(vertBase + 4, true); normals[offset++] = ny; vertices[offset] = dv.getFloat32(vertBase + 8, true); normals[offset++] = nz; } } return { normals, vertices }; } function computeCentroid(vertices) { let cx = 0, cy = 0, cz = 0; const length_ = vertices.length; for (let index = 0; index < length_; index += 3) { cx += vertices[index] ?? 0; cy += vertices[index + 1] ?? 0; cz += vertices[index + 2] ?? 0; } const numberVertices = length_ / 3; return [cx / numberVertices, cy / numberVertices, cz / numberVertices]; } function parseSTL(_x) { return _parseSTL.apply(this, arguments); } function _parseSTL() { _parseSTL = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (file) { const buffer = yield file.arrayBuffer(); if (!isBinary(buffer)) throw new Error('Failed to parse STL file. ASCII STL support is not implemented.'); const { normals, vertices } = readBinarySTL(buffer); return { centroid: computeCentroid(vertices), normals, vertices }; }); return _parseSTL.apply(this, arguments); } /***/ }, /***/ 39844 /*!*************************************************************!*\ !*** ./libs/utils/src/lib/geometry/vector-to-angulation.ts ***! \*************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ vectorToAngulation: () => (/* binding */ vectorToAngulation) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); function vectorToAngulation(v) { let cc = -Math.asin(v[2]) / Math.PI * 180; let rl = -Math.atan2(v[0], v[1]) / Math.PI * 180; if (cc > 90 || cc < -90 || rl > 90 || rl < -90) { const v2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.scale(v2, v, -1); cc = -Math.asin(v2[2]) / Math.PI * 180; rl = -Math.atan2(v2[0], v2[1]) / Math.PI * 180; } return { ax: 0, cc, rl }; } /***/ }, /***/ 84503 /*!*******************************************!*\ !*** ./libs/utils/src/lib/import-json.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ importFromJsonFile: () => (/* binding */ importFromJsonFile) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _pick_file_from_disk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pick-file-from-disk */ 22344); function importFromJsonFile(_x) { return _importFromJsonFile.apply(this, arguments); } function _importFromJsonFile() { _importFromJsonFile = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (document, accept = 'application/json,.json') { const file = yield (0,_pick_file_from_disk__WEBPACK_IMPORTED_MODULE_1__.pickFileFromDisk)(document, accept); if (!file) return; try { const fileContents = yield file.text(); return JSON.parse(fileContents); } catch (error) { console.error('Failed to parse JSON file:', error); throw new Error('The selected file is not a valid JSON document.'); } }); return _importFromJsonFile.apply(this, arguments); } /***/ }, /***/ 66222 /*!**********************************************!*\ !*** ./libs/utils/src/lib/increment-name.ts ***! \**********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ incrementName: () => (/* binding */ incrementName) /* harmony export */ }); /** * Given a base name and a list of existing names, the base name will be suffixed with * the lowest number that doesn't exist as a suffix of the base name in the existing names. */ function incrementName(name, existingNames, maxLength) { let n = 1; const incrementedName = index => { const suffix = ` ${index}`; if (maxLength === undefined || name.length + suffix.length <= maxLength) { return `${name}${suffix}`; } return `${name.slice(0, maxLength - suffix.length)}${suffix}`; }; let newName = incrementedName(n); while (existingNames.includes(newName)) { n++; newName = incrementedName(n); } return newName; } /***/ }, /***/ 42035 /*!********************************************************************!*\ !*** ./libs/utils/src/lib/injection-tokens/env-injection-token.ts ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ENV: () => (/* binding */ ENV) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); const ENV = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('ENV'); /***/ }, /***/ 13253 /*!*****************************************************************************!*\ !*** ./libs/utils/src/lib/injection-tokens/is-dev-build-injection-token.ts ***! \*****************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ IS_DEV_BUILD: () => (/* binding */ IS_DEV_BUILD) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 36973); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _env_injection_token__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./env-injection-token */ 42035); /** * Whether this is a non-production build, i.e. the single definition of * "dev build" for the app. Inject it instead of reading `ENV.production` or * calling `isDevMode()` directly. */ const IS_DEV_BUILD = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('IS_DEV_BUILD', { factory: () => { const env = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_env_injection_token__WEBPACK_IMPORTED_MODULE_2__.ENV, { optional: true }); return env ? !env.production : (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.isDevMode)(); } }); /***/ }, /***/ 28235 /*!*********************************************!*\ !*** ./libs/utils/src/lib/interpolation.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cubicInterpolator: () => (/* binding */ cubicInterpolator), /* harmony export */ linearInterpolationByDistance2D: () => (/* binding */ linearInterpolationByDistance2D) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); const DEFAULT_CONFIG = { cubicTension: 0, isPeriodic: false }; /** * Returns a function that calculates interpolated points on a path. * Semi-ported from Smooth.js as that library has no NPM / Typescript support. * @param points The points to interpolate * @returns An interpolation function */ function cubicInterpolator(points, options = {}) { const config = { ...DEFAULT_CONFIG, ...options }; const tangentFactor = vecOf(1 - Math.max(0, Math.min(1, config.cubicTension))); const length = points.length; function getClippedInput(index) { if (0 <= index && index < length) { return points[index]; } else if (config.isPeriodic) { return points[clipPeriodic(index, length)]; } else { return points[clipMirror(index, length)]; } } function getTangent(k) { return vecOp(v => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(v, getClippedInput(k + 1), getClippedInput(k - 1)); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(v, v, tangentFactor); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.divide(v, v, vecOf(2)); }); } return t => { const k = Math.floor(t); const m = [getTangent(k), getTangent(k + 1)]; const p = [getClippedInput(k), getClippedInput(k + 1)]; const tv = vecOf(t); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(tv, tv, vecOf(k)); const t2 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(t2, tv, tv); const t3 = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(t3, tv, t2); // Smooth.js used: // (((2 * t3) - (3 * t2) + 1) * p[0]) + // ((t3 - (2 * t2) + t) * m[0]) + // (((-2 * t3) + (3 * t2)) * p[1]) + // ((t3 - t2) * m[1]) // a = ((2 * t3) - (3 * t2) + 1) const a = vecOp(v => { // x = 2 * t3 const x = vecOp(vv => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(vv, vecOf(2), t3); }); // y = 3 * t2 const y = vecOp(vv => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(vv, vecOf(3), t2); }); // v = x - y gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(v, x, y); // v += 1 gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(v, v, vecOf(1)); }); // a *= p[0] gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(a, a, p[0]); // b = (t3 - (2 * t2) + t) const b = vecOp(v => { // x = 2 * t2 const x = vecOp(vv => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(vv, vecOf(2), t2); }); // v = t3 - x gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(v, t3, x); // v += t gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(v, v, tv); }); // b *= m[0] gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(b, b, m[0]); // c = ((-2 * t3) + (3 * t2)) const c = vecOp(v => { // x = -2 * t3 const x = vecOp(vv => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(vv, vecOf(-2), t3); }); // y = 3 * t2 const y = vecOp(vv => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(vv, vecOf(3), t2); }); // v = x + y gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(v, x, y); }); // c *= p[1] gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(c, c, p[1]); // d = (t3 - t2) const d = vecOp(v => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.subtract(v, t3, t2); }); // d *= m[1] gl_matrix__WEBPACK_IMPORTED_MODULE_0__.multiply(d, d, m[1]); // out = a + b + c + d return vecOp(out => { gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(out, a, b); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(out, out, c); gl_matrix__WEBPACK_IMPORTED_MODULE_0__.add(out, out, d); }); }; } function clipMirror(index, n) { const period = 2 * (n - 1); // period of index mirroring function index = clipPeriodic(index, period); if (index > n - 1) { index = period - index; } // flip when out of bounds return index; } function clipPeriodic(index, n) { index = index % n; // wrap if (index < 0) { index += n; } // if negative, wrap back around return index; } function vecOf(n) { return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(n, n, n); } function vecOp(block) { const vec = gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(); block(vec); return vec; } function linearInterpolationByDistance2D(points, step = 1) { if (points.length < 2) return [...points]; const result = [points[0]]; let remainder = 0; for (let index = 0; index < points.length - 1; index++) { const [x0, y0] = points[index]; const [x1, y1] = points[index + 1]; const dx = x1 - x0; const dy = y1 - y0; const segLength = Math.hypot(dx, dy); if (segLength === 0) continue; const ux = dx / segLength; const uy = dy / segLength; let distance = remainder; while (distance < segLength) { result.push([x0 + ux * distance, y0 + uy * distance]); distance += step; } remainder = distance - segLength; } result.push(points.at(-1)); return result; } /***/ }, /***/ 95349 /*!********************************************!*\ !*** ./libs/utils/src/lib/is-equal-set.ts ***! \********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ isEqualSet: () => (/* binding */ isEqualSet) /* harmony export */ }); function isEqualSet(a, b) { return a.size === b.size && [...a].every(value => b.has(value)); } /***/ }, /***/ 46084 /*!**************************************!*\ !*** ./libs/utils/src/lib/matrix.ts ***! \**************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ mat3ToArray: () => (/* binding */ mat3ToArray) /* harmony export */ }); function mat3ToArray(mat) { return [mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], mat[6], mat[7], mat[8]]; } /***/ }, /***/ 83775 /*!*******************************************!*\ !*** ./libs/utils/src/lib/memoization.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ memoize: () => (/* binding */ memoize), /* harmony export */ memoizeByReference: () => (/* binding */ memoizeByReference) /* harmony export */ }); function memoize(function_, resolver = defaultResolver) { const cache = new Map(); function memo(...arguments_) { const key = resolver(...arguments_); if (!cache.has(key)) { cache.set(key, function_(...arguments_)); } return cache.get(key); } memo.dropEntry = (...arguments_) => { const key = resolver(...arguments_); cache.delete(key); }; memo.dropEntryByKey = key => { cache.delete(key); }; memo.clear = () => { cache.clear(); }; memo.unmemoized = (...arguments_) => { return function_(...arguments_); }; return memo; } function defaultResolver(...arguments_) { return JSON.stringify(arguments_); } function memoizeByReference(function_, resolver = defaultResolver) { const cache = new Map(); function memo(...arguments_) { const key = resolver(...arguments_); if (!cache.has(key)) { const value = function_(...arguments_); cache.set(key, { refs: arguments_, value }); return value; } const { refs, value } = cache.get(key); let stale = false; for (const [index, parameter] of arguments_.entries()) { if (parameter !== refs[index]) { stale = true; break; } } if (stale) { const value = function_(...arguments_); cache.set(key, { refs: arguments_, value }); return value; } return value; } memo.dropEntry = (...arguments_) => { const key = resolver(...arguments_); cache.delete(key); }; memo.dropEntryByKey = key => { cache.delete(key); }; memo.clear = () => { cache.clear(); }; memo.unmemoized = (...arguments_) => { return function_(...arguments_); }; return memo; } /***/ }, /***/ 71717 /*!******************************************!*\ !*** ./libs/utils/src/lib/multiphase.ts ***! \******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ describePhase: () => (/* binding */ describePhase), /* harmony export */ formatPhaseIdentification: () => (/* binding */ formatPhaseIdentification), /* harmony export */ looksMultiphase: () => (/* binding */ looksMultiphase), /* harmony export */ separatePhases: () => (/* binding */ separatePhases), /* harmony export */ toFiniteNumber: () => (/* binding */ toFiniteNumber) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); /* harmony import */ var _tomoverse_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tomoverse/types */ 25575); const MIN_POSITION_KEYS_FOR_REPEATED_GEOMETRY = 8; const MIN_REPEATED_POSITION_RATIO = 0.6; const toFiniteNumber = value => { if (typeof value === 'number') { return Number.isFinite(value) ? value : undefined; } if (typeof value === 'string') { const numericValue = Number.parseFloat(value.trim()); return Number.isFinite(numericValue) ? numericValue : undefined; } return undefined; }; const toNumberTuple = value => { const rawArray = Array.isArray(value) ? value : [value]; const values = rawArray.flatMap(item => Array.isArray(item) ? item : [item]); const parsed = values.map(item => toFiniteNumber(item)).filter(item => item !== undefined); return parsed.length >= 3 ? parsed : undefined; }; const TP_TOKEN = /^TP(\d+)PC(\d+)$/; const GATE_TOKEN = /^GATE_(\d+)_OF_(\d+)$/; const parseScanOptions = metadata => { const raw = metadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.ScanOptions]?.Value; if (!raw) return undefined; // CS may arrive as a DICOMweb array or a backslash-joined string. const tokens = (Array.isArray(raw) ? raw : [raw]).flatMap(value => typeof value === 'string' ? value.split('\\') : []); let result; for (const token of tokens) { const tp = TP_TOKEN.exec(token); if (tp) { result = { ...result, phasePercent: Number(tp[1]), rrIntervalMs: Number(tp[2]) }; continue; } const gate = GATE_TOKEN.exec(token); if (gate) { result = { ...result, gateCount: Number(gate[2]), gateIndex: Number(gate[1]) }; } } return result; }; const positionKeyFromMetadata = metadata => { const imagePosition = metadata[_tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.ImagePositionPatient]?.Value; const tuple = toNumberTuple(imagePosition); if (tuple) { return tuple.slice(0, 3).map(value => value.toFixed(4)).join('|'); } const sliceLocation = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.SliceLocation)); if (sliceLocation !== undefined) { return `slice:${sliceLocation.toFixed(4)}`; } return undefined; }; const resolveExplicitPhase = metadata => { // ScanOptions first: these series carry a constant AcquisitionNumber, so otherwise they would // fall through to geometry. const scanOptions = parseScanOptions(metadata); if (scanOptions?.phasePercent !== undefined) { return { id: `phase:${scanOptions.phasePercent}`, label: `Phase ${scanOptions.phasePercent}`, order: scanOptions.phasePercent }; } if (scanOptions?.gateIndex !== undefined) { return { id: `gate:${scanOptions.gateIndex}`, label: `Phase ${scanOptions.gateIndex}`, order: scanOptions.gateIndex }; } const acquisitionNumber = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.AcquisitionNumber)); if (acquisitionNumber !== undefined) { return { id: `acquisition:${acquisitionNumber}`, label: `Phase ${acquisitionNumber}`, order: acquisitionNumber }; } const temporalPosition = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TemporalPositionIdentifier)); if (temporalPosition !== undefined) { return { id: `temporal:${temporalPosition}`, label: `Phase ${temporalPosition}`, order: temporalPosition }; } const triggerTime = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TriggerTime)); if (triggerTime !== undefined) { return { id: `trigger:${triggerTime}`, label: `Phase ${triggerTime}`, order: triggerTime }; } const phaseVector = (0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.PhaseVector); const phaseVectorNumber = toFiniteNumber(phaseVector); if (phaseVectorNumber !== undefined) { return { id: `vector:${phaseVectorNumber}`, label: `Phase ${phaseVectorNumber}`, order: phaseVectorNumber }; } if (Array.isArray(phaseVector)) { const values = phaseVector.map(Number).filter(value => Number.isFinite(value)); if (values.length > 0) { return { id: `vector:${values.join('-')}`, label: `Phase ${values.join('.')}`, order: values[0] ?? 0 }; } } return undefined; }; const toSortedPhaseList = groups => [...groups.entries()].map(([id, group]) => ({ id, label: group.label, memberIds: group.memberIds, order: group.order })).toSorted((a, b) => { const orderDiff = a.order - b.order; if (orderDiff !== 0) return orderDiff; return a.id.localeCompare(b.id); }); const groupByExplicitPhase = instances => { const groups = new Map(); for (const instance of instances) { const phase = resolveExplicitPhase(instance.metadata); if (!phase) { return []; } const group = groups.get(phase.id); if (group) { group.memberIds.push(instance.id); continue; } groups.set(phase.id, { label: phase.label, memberIds: [instance.id], order: phase.order }); } return toSortedPhaseList(groups); }; const groupByGeometryPhase = instances => { const sorted = instances.toSorted((a, b) => a.sortOrder - b.sortOrder); // Assumes phases are stored as contiguous blocks (all of phase 1, then all of phase 2, …): // start a new phase whenever a slice position reappears within the current one. const phases = []; let current; for (const instance of sorted) { const positionKey = positionKeyFromMetadata(instance.metadata); if (!positionKey) { return []; } if (!current || current.positions.has(positionKey)) { current = { memberIds: [], positions: new Set() }; phases.push(current); } current.memberIds.push(instance.id); current.positions.add(positionKey); } const [firstPhase, ...otherPhases] = phases; if (!firstPhase || otherPhases.length === 0) { return []; } // Reject ragged splits (e.g. a stray duplicate slice) where phases don't span the same positions. const allPhasesShareGeometry = otherPhases.every(phase => phase.positions.size === firstPhase.positions.size && [...phase.positions].every(position => firstPhase.positions.has(position))); if (!allPhasesShareGeometry) { return []; } return phases.map((phase, index) => ({ id: `geometry:${index + 1}`, label: `Phase ${index + 1}`, memberIds: phase.memberIds, order: index + 1 })); }; /** * Separate a series' instances into phases — explicit phase tags first, then a geometry fallback. * Returns [] when the series is single-phase or cannot be cleanly separated. */ const separatePhases = instances => { const explicitPhases = groupByExplicitPhase(instances); const groups = explicitPhases.length > 1 ? explicitPhases : groupByGeometryPhase(instances); if (groups.length <= 1) { return []; } // Reduce to a stable sequential ordinal; the UI composes the display word and units. return groups.map((group, index) => ({ ...group, label: String(index + 1) })); }; const maxTagValue = (instances, tag) => { let max = 1; for (const { metadata } of instances) { const value = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, tag)); if (value !== undefined) { max = Math.max(max, value); } } return max; }; const hasRepeatedGeometry = instances => { const positionCounts = new Map(); for (const { metadata } of instances) { const positionKey = positionKeyFromMetadata(metadata); if (positionKey) { positionCounts.set(positionKey, (positionCounts.get(positionKey) ?? 0) + 1); } } const repeats = [...positionCounts.values()]; const repeatedRatio = positionCounts.size > 0 ? repeats.filter(count => count > 1).length / positionCounts.size : 0; return positionCounts.size >= MIN_POSITION_KEYS_FOR_REPEATED_GEOMETRY && repeatedRatio >= MIN_REPEATED_POSITION_RATIO && Math.max(...repeats, 0) > 1; }; /** * Whether a series *appears* multiphase regardless of whether `separatePhases` can split it — used * only to detect the "looks multiphase but couldn't be separated" case. Two signals independent of * the separation keys: a header declaration (`NumberOfPhases` / `NumberOfTemporalPositions` / * `CardiacNumberOfImages` > 1) or repeated slice geometry. */ const looksMultiphase = instances => { const headerDeclaresMultiphase = maxTagValue(instances, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.NumberOfPhases) > 1 || maxTagValue(instances, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.NumberOfTemporalPositions) > 1 || maxTagValue(instances, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.CardiacNumberOfImages) > 1; return headerDeclaresMultiphase || hasRepeatedGeometry(instances); }; /** * Cardiac identification for a phase from a representative instance's metadata. Returns undefined * for non-gated volumes (no trigger time) — those are labelled "Volume", not "Phase". */ const describePhase = metadata => { if (!metadata) return undefined; // ScanOptions carries the phase % (and R-R via the RRRR suffix) directly — preferred, as the // standard trigger-time/nominal-interval tags are usually absent on this data. const scanOptions = parseScanOptions(metadata); if (scanOptions?.phasePercent !== undefined) { const triggerTime = scanOptions.rrIntervalMs !== undefined && scanOptions.rrIntervalMs > 0 ? Math.round(scanOptions.phasePercent / 100 * scanOptions.rrIntervalMs) : undefined; return { rrPercent: scanOptions.phasePercent, triggerTime }; } const triggerTime = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.TriggerTime)); if (triggerTime === undefined) return undefined; const nominalInterval = toFiniteNumber((0,_tomoverse_types__WEBPACK_IMPORTED_MODULE_1__.getTagValue)(metadata, _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.DicomTagId.NominalInterval)); const rrPercent = nominalInterval !== undefined && nominalInterval > 0 ? triggerTime / nominalInterval * 100 : undefined; return { rrPercent, triggerTime }; }; const formatPhaseIdentification = (identification, labels) => { if (!identification) return undefined; if (identification.rrPercent !== undefined) { return `${Math.round(identification.rrPercent)}%`; } if (identification.triggerTime !== undefined) { return `${identification.triggerTime} ${labels.triggerUnit}`; } return undefined; }; /***/ }, /***/ 60786 /*!*************************************************!*\ !*** ./libs/utils/src/lib/object3d-geometry.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ deserializeObject3DGeometry: () => (/* binding */ deserializeObject3DGeometry), /* harmony export */ hashObject3DGeometry: () => (/* binding */ hashObject3DGeometry), /* harmony export */ makeObject3DGeometryBlob: () => (/* binding */ makeObject3DGeometryBlob), /* harmony export */ readObject3DGeometryBlob: () => (/* binding */ readObject3DGeometryBlob), /* harmony export */ withShell: () => (/* binding */ withShell) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _msgpack_msgpack__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @msgpack/msgpack */ 12555); /* harmony import */ var _msgpack_msgpack__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @msgpack/msgpack */ 3555); /* harmony import */ var _geometry_convex_hull__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./geometry/convex-hull */ 16147); function hashObject3DGeometry(_x) { return _hashObject3DGeometry.apply(this, arguments); } function _hashObject3DGeometry() { _hashObject3DGeometry = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (geo) { const encoded = (0,_msgpack_msgpack__WEBPACK_IMPORTED_MODULE_1__.encode)(geo); const buffer = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength); const hashBuffer = yield crypto.subtle.digest('SHA-256', buffer); return [...new Uint8Array(hashBuffer)].slice(0, 16) // 16 bytes = 32 hex chars .map(b => b.toString(16).padStart(2, '0')).join(''); }); return _hashObject3DGeometry.apply(this, arguments); } function makeObject3DGeometryBlob(geo) { const encoded = (0,_msgpack_msgpack__WEBPACK_IMPORTED_MODULE_1__.encode)(geo); const buffer = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength); return new Blob([buffer], { type: 'application/octet-stream' }); } function readObject3DGeometryBlob(_x2) { return _readObject3DGeometryBlob.apply(this, arguments); } function _readObject3DGeometryBlob() { _readObject3DGeometryBlob = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (blob) { const buffer = yield blob.arrayBuffer(); return deserializeObject3DGeometry(buffer); }); return _readObject3DGeometryBlob.apply(this, arguments); } function deserializeObject3DGeometry(buffer) { try { const decoded = (0,_msgpack_msgpack__WEBPACK_IMPORTED_MODULE_2__.decode)(new Uint8Array(buffer)); // NOTE: msgpack encodes all bytearrays as `Uint8Array` so we need to cast return { centroid: decoded.centroid, indices: new Uint32Array(toAlignedBuffer(decoded.indices)), normals: new Float32Array(toAlignedBuffer(decoded.normals)), shell: decoded.shell ? { bounds: decoded.shell.bounds, indices: new Uint32Array(toAlignedBuffer(decoded.shell.indices)), vertices: new Float32Array(toAlignedBuffer(decoded.shell.vertices)) } : undefined, vertices: new Float32Array(toAlignedBuffer(decoded.vertices)) }; } catch (error) { console.warn('Invalid geometry data', error); return; } } // eslint-disable-next-line @typescript-eslint/no-explicit-any function toAlignedBuffer(array) { return array.buffer.slice(array.byteOffset, array.byteOffset + array.byteLength); } function withShell(geometry) { if (geometry.shell) return geometry; return { ...geometry, shell: (0,_geometry_convex_hull__WEBPACK_IMPORTED_MODULE_3__.computeConvexHull)(geometry.vertices) }; } /***/ }, /***/ 22344 /*!***************************************************!*\ !*** ./libs/utils/src/lib/pick-file-from-disk.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ pickFileFromDisk: () => (/* binding */ pickFileFromDisk) /* harmony export */ }); function pickFileFromDisk(document, accept = 'application/json,.json') { return new Promise(resolve => { const input = document.createElement('input'); input.type = 'file'; input.accept = accept; const cleanup = () => { input.removeEventListener('change', handleSelection); input.removeEventListener('cancel', handleCancel); }; const handleSelection = () => { const file = input.files?.[0] ?? undefined; cleanup(); resolve(file); }; const handleCancel = () => { cleanup(); resolve(undefined); }; input.addEventListener('change', handleSelection); input.addEventListener('cancel', handleCancel); input.click(); }); } /***/ }, /***/ 10272 /*!*****************************************************!*\ !*** ./libs/utils/src/lib/pipes/dicom-date.pipe.ts ***! \*****************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DICOM_DATE_FORMAT: () => (/* binding */ DICOM_DATE_FORMAT), /* harmony export */ DICOM_DATE_TIME_FORMAT: () => (/* binding */ DICOM_DATE_TIME_FORMAT), /* harmony export */ DicomDatePipe: () => (/* binding */ DicomDatePipe) /* harmony export */ }); /* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 32229); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 14975); /* harmony import */ var _dicom_parse_dicom_date_helper__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../dicom/parse-dicom-date.helper */ 32495); /** Applies a DICOM TM value onto the date, when parseable. */ function withDicomTime(date, time) { const match = /^(\d{2})(\d{2})?(\d{2})?/.exec(time?.trim() ?? ''); if (!match) return date; const result = new Date(date); result.setHours(Number(match[1]), Number(match[2] ?? 0), Number(match[3] ?? 0), 0); return result; } /** Canonical app-wide date formats. */ const DICOM_DATE_FORMAT = 'yyyy-MMM-dd'; const DICOM_DATE_TIME_FORMAT = 'yyyy-MMM-dd HH:mm'; /** * Single source of truth for formatting dates across the app. * * Accepts a DICOM `YYYYMMDD` string, an ISO datetime string, or a `Date`, and renders it with the * canonical `yyyy-MMM-dd` pattern (or `yyyy-MMM-dd HH:mm` when `withTime` is set). */ class DicomDatePipe { datePipe = new _angular_common__WEBPACK_IMPORTED_MODULE_0__.DatePipe((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_2__.LOCALE_ID)); transform(value, withTime = false, dicomTime) { const date = this.toDate(value); if (!date) { return typeof value === 'string' && value ? value : undefined; } const format = withTime ? DICOM_DATE_TIME_FORMAT : DICOM_DATE_FORMAT; return this.datePipe.transform(withDicomTime(date, dicomTime), format) ?? undefined; } toDate(value) { if (!value) return undefined; if (value instanceof Date) { return Number.isNaN(value.getTime()) ? undefined : value; } const dicom = (0,_dicom_parse_dicom_date_helper__WEBPACK_IMPORTED_MODULE_3__.parseDicomDate)(value); if (dicom) return dicom; const parsed = new Date(value); return Number.isNaN(parsed.getTime()) ? undefined : parsed; } static ɵfac = function DicomDatePipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomDatePipe)(); }; static ɵpipe = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_2__["ɵɵdefinePipe"]({ name: "dicomDate", type: DicomDatePipe, pure: true }); } /***/ }, /***/ 61971 /*!************************************************************!*\ !*** ./libs/utils/src/lib/pipes/dicom-person-name.pipe.ts ***! \************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DicomPersonNamePipe: () => (/* binding */ DicomPersonNamePipe) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 14975); /** * Renders a DICOM person name (PN) for display. Takes the alphabetic component group (before the first `=`), * splits it into `family^given^middle^prefix^suffix`, and shows the family name first. * Prefix/suffix are omitted. Empty/undefined returns `undefined`. * * Example: `DOE^JANE^Q` becomes `DOE, JANE Q`. */ class DicomPersonNamePipe { transform(value) { if (!value) return undefined; const alphabetic = value.split('=')[0] ?? ''; const [family = '', given = '', middle = ''] = alphabetic.split('^').map(component => component.replaceAll(/\s+/g, ' ').trim()); const givenMiddle = [given, middle].filter(Boolean).join(' '); const display = family && givenMiddle ? `${family}, ${givenMiddle}` : family || givenMiddle; return display || undefined; } static ɵfac = function DicomPersonNamePipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DicomPersonNamePipe)(); }; static ɵpipe = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "dicomPersonName", type: DicomPersonNamePipe, pure: true }); } /***/ }, /***/ 4251 /*!**************************************************************!*\ !*** ./libs/utils/src/lib/pipes/exponential-backoff.pipe.ts ***! \**************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ retryWithBackoff: () => (/* binding */ retryWithBackoff) /* harmony export */ }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 38647); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 41434); const retryWithBackoff = (initialDelay = 1000, backoffFactor = 2, maxRetries) => { return source => source.pipe((0,rxjs__WEBPACK_IMPORTED_MODULE_1__.retry)({ count: maxRetries, delay: (error, retryCount) => (0,rxjs__WEBPACK_IMPORTED_MODULE_0__.timer)(initialDelay * Math.pow(backoffFactor, retryCount - 1)), resetOnSuccess: true })); }; /***/ }, /***/ 261 /*!**************************************************!*\ !*** ./libs/utils/src/lib/pipes/or-dash.pipe.ts ***! \**************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ NO_DATA_PLACEHOLDER: () => (/* binding */ NO_DATA_PLACEHOLDER), /* harmony export */ OrDashPipe: () => (/* binding */ OrDashPipe), /* harmony export */ hasDisplayValue: () => (/* binding */ hasDisplayValue) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 14975); /** Unified placeholder shown for a missing/empty display value across the app's tables. */ const NO_DATA_PLACEHOLDER = '-'; /** * Whether a value counts as "present" for display. `0` and `false` are present (real values). * `null`/`undefined`, blank strings, and empty arrays are not. */ function hasDisplayValue(value) { if (value == undefined) return false; if (typeof value === 'string') return value.trim() !== ''; if (Array.isArray(value)) return value.length > 0; return true; } /** Renders a value as-is when present, or the unified `-` placeholder when absent (keeps `0`). */ class OrDashPipe { transform(value) { return hasDisplayValue(value) ? value : NO_DATA_PLACEHOLDER; } static ɵfac = function OrDashPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || OrDashPipe)(); }; static ɵpipe = /*@__PURE__*/_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "orDash", type: OrDashPipe, pure: true }); } /***/ }, /***/ 60174 /*!****************************************!*\ !*** ./libs/utils/src/lib/position.ts ***! \****************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ORIGIN: () => (/* binding */ ORIGIN), /* harmony export */ UNINIT: () => (/* binding */ UNINIT), /* harmony export */ parsePosition: () => (/* binding */ parsePosition), /* harmony export */ position: () => (/* binding */ position), /* harmony export */ positionIsUninitialized: () => (/* binding */ positionIsUninitialized), /* harmony export */ positionToVec3: () => (/* binding */ positionToVec3), /* harmony export */ positionsEqual: () => (/* binding */ positionsEqual), /* harmony export */ vec3ToPosition: () => (/* binding */ vec3ToPosition) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 87396); // NOTE: This was originally `NaN`, but as JSON doesn't support // NaN/Infinity values it made more sense to use this. // Since our scale is in cm, this should be much larger than we'll // ever encounter in a volume. const UNINIT_VAL = 99_999; const ORIGIN = [0, 0, 0]; const UNINIT = [UNINIT_VAL, UNINIT_VAL, UNINIT_VAL]; function position(x, y, z) { return [x, y, z]; } function parsePosition(source) { const [a, b, c] = source; if (a === undefined || b === undefined || c === undefined) throw new Error('Invalid position'); return position(a, b, c); } function positionsEqual(a, b) { return a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; } function vec3ToPosition(vec) { return [vec[0], vec[1], vec[2]]; } function positionToVec3(position) { return gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromValues(position[0], position[1], position[2]); } function positionIsUninitialized(position) { return position.some(number_ => number_ >= UNINIT_VAL); } /***/ }, /***/ 75379 /*!****************************************!*\ !*** ./libs/utils/src/lib/promises.ts ***! \****************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ waitAsync: () => (/* binding */ waitAsync), /* harmony export */ withTimeout: () => (/* binding */ withTimeout) /* harmony export */ }); function waitAsync(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); } /** * Rejects with `message` after `ms` if `promise` hasn't settled by then. For wrapping calls into * libraries that can silently never settle their own promise on certain failures, so a stuck * dependency surfaces as a catchable error instead of hanging the caller forever. */ function withTimeout(promise, ms, message) { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => reject(new Error(message)), ms); promise.then(value => { clearTimeout(timeoutId); resolve(value); }, error => { clearTimeout(timeoutId); reject(error); }); }); } /***/ }, /***/ 12896 /*!*************************************!*\ !*** ./libs/utils/src/lib/range.ts ***! \*************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ range: () => (/* binding */ range) /* harmony export */ }); function range(start, stop, step = 1) { return Array.from({ length: (stop - start) / step + 1 }, (_, index) => start + index * step); } /***/ }, /***/ 1554 /*!***********************************************************!*\ !*** ./libs/utils/src/lib/segmentation/region-growing.ts ***! \***********************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ autoSeedFromVolume: () => (/* binding */ autoSeedFromVolume), /* harmony export */ resolveSeedIJK: () => (/* binding */ resolveSeedIJK) /* harmony export */ }); /* harmony import */ var _cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../cornerstone/cornerstone-volume */ 25489); // Sample the central third every N voxels. At typical 0.5–1 mm/voxel this gives // one seed per ~10–15 mm, enough to seed both sides of the blood pool even when // cardiac valve planes break 6-connectivity between the left and right heart. const GRID_STEP = 15; /** Returns HU-range voxel positions on a coarse grid within the central third of the volume. */ function autoSeedFromVolume(volumeData, minHU, maxHU, gridStep = GRID_STEP) { const [dimX, dimY, dimZ] = volumeData.dimensions; const dimXY = dimX * dimY; const { voxelData } = volumeData; const indexMin = Math.floor(dimX / 3); const indexMax = Math.ceil(dimX * 2 / 3); const indexMin_ = Math.floor(dimY / 3); const indexMax_ = Math.ceil(dimY * 2 / 3); const kMin = Math.floor(dimZ / 3); const kMax = Math.ceil(dimZ * 2 / 3); const seeds = []; for (let k = kMin; k < kMax; k += gridStep) { for (let index = indexMin_; index < indexMax_; index += gridStep) { for (let index_ = indexMin; index_ < indexMax; index_ += gridStep) { const hu = voxelData[index_ + index * dimX + k * dimXY]; if (hu >= minHU && hu <= maxHU) seeds.push([index_, index, k]); } } } return seeds; } /** Returns IJK seed coordinates from a world-space position, or auto-seeds from the central third of the volume when no position is provided. */ function resolveSeedIJK(volumeData, minHU, maxHU, seedWorldPos, gridStep) { if (!seedWorldPos) return autoSeedFromVolume(volumeData, minHU, maxHU, gridStep); const f = (0,_cornerstone_cornerstone_volume__WEBPACK_IMPORTED_MODULE_0__.worldToIndex)(volumeData, seedWorldPos); return [[Math.round(f[0]), Math.round(f[1]), Math.round(f[2])]]; } /***/ }, /***/ 72024 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/segmentation/vascular-mask-compute.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ PREVIEW_DOWNSAMPLE: () => (/* binding */ PREVIEW_DOWNSAMPLE), /* harmony export */ VASCULAR_MASK_LABELS: () => (/* binding */ VASCULAR_MASK_LABELS), /* harmony export */ autoSeedFromVolumeData: () => (/* binding */ autoSeedFromVolumeData), /* harmony export */ buildLabelMask: () => (/* binding */ buildLabelMask), /* harmony export */ buildOutlierMask: () => (/* binding */ buildOutlierMask), /* harmony export */ computeAutoVascularThresholds: () => (/* binding */ computeAutoVascularThresholds), /* harmony export */ computePercentileRange: () => (/* binding */ computePercentileRange), /* harmony export */ computeThresholdMask: () => (/* binding */ computeThresholdMask), /* harmony export */ dilateMask: () => (/* binding */ dilateMask), /* harmony export */ downsampleVolume: () => (/* binding */ downsampleVolume), /* harmony export */ erodeBinaryMask: () => (/* binding */ erodeBinaryMask), /* harmony export */ pruneSmallClusters: () => (/* binding */ pruneSmallClusters), /* harmony export */ regionGrow: () => (/* binding */ regionGrow), /* harmony export */ upsampleLabelMask: () => (/* binding */ upsampleLabelMask), /* harmony export */ vascularRequestState: () => (/* binding */ vascularRequestState) /* harmony export */ }); // Pure vascular mask computation. // Functions above the "Main-thread helpers" section have no framework or // Cornerstone imports and are safe to call from within vascular-mask.worker.ts. const GRID_STEP = 15; const MIN_CLUSTER_SIZE = 30_000; /** Per-axis stride of the preview copy (1/64 of the work). Point sampling * keeps real HU values so thresholds behave like full res; thin structures * may alias — the slide-end full run is exact. */ const PREVIEW_DOWNSAMPLE = 4; /** Returns HU-range voxel positions on a coarse grid within the central third of the volume. */ function autoSeedFromVolumeData(voxelData, dimensions, minHU, maxHU, gridStep = GRID_STEP) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const seeds = []; const colMin = Math.trunc(dimX / 3); const colMax = Math.ceil(dimX * 2 / 3); const rowMin = Math.trunc(dimY / 3); const rowMax = Math.ceil(dimY * 2 / 3); const sliceMin = Math.trunc(dimZ / 3); const sliceMax = Math.ceil(dimZ * 2 / 3); for (let sliceIndex = sliceMin; sliceIndex < sliceMax; sliceIndex += gridStep) { for (let rowIndex = rowMin; rowIndex < rowMax; rowIndex += gridStep) { for (let colIndex = colMin; colIndex < colMax; colIndex += gridStep) { const hu = voxelData[colIndex + rowIndex * dimX + sliceIndex * dimXY]; if (hu >= minHU && hu <= maxHU) seeds.push([colIndex, rowIndex, sliceIndex]); } } } return seeds; } function isSeedInBounds(si, sj, sk, dimX, dimY, dimZ) { return si >= 0 && si < dimX && sj >= 0 && sj < dimY && sk >= 0 && sk < dimZ; } /** Initializes the BFS queue from seeds; returns the initial tail position. */ function seedRegionQueue(seeds, mask, queue, voxelData, dimX, dimY, dimZ, dimXY, minHU, maxHU, gateMask) { let tail = 0; for (const seed of seeds) { const si = Math.round(seed[0]); const sj = Math.round(seed[1]); const sk = Math.round(seed[2]); if (!isSeedInBounds(si, sj, sk, dimX, dimY, dimZ)) continue; const seedIndex = si + sj * dimX + sk * dimXY; if (mask[seedIndex]) continue; const seedHu = voxelData[seedIndex]; if (gateMask ? !gateMask[seedIndex] : seedHu < minHU || seedHu > maxHU) continue; mask[seedIndex] = 1; queue[tail++] = seedIndex; } return tail; } /** Enqueues a region neighbor if passable. Returns the updated tail. */ function tryEnqueueRegionNeighbor(ni, mask, queue, tail, voxelData, minHU, maxHU, gateMask) { if (mask[ni]) return tail; const hu = voxelData[ni]; const passable = gateMask ? !!gateMask[ni] : hu >= minHU && hu <= maxHU; if (!passable) return tail; mask[ni] = 1; queue[tail] = ni; return tail + 1; } /** 6-connectivity BFS flood fill from seeds; gate mask substitutes HU checks when provided. */ function regionGrow(voxelData, dimensions, seeds, minHU, maxHU, out, gateMask, scratchQueue) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const voxelCount = dimXY * dimZ; const mask = out ?? new Uint8Array(voxelCount); const queue = scratchQueue ?? new Int32Array(voxelCount); let head = 0; let tail = seedRegionQueue(seeds, mask, queue, voxelData, dimX, dimY, dimZ, dimXY, minHU, maxHU, gateMask); while (head < tail) { const index = queue[head++]; const z = Math.trunc(index / dimXY); const rem = index - z * dimXY; const y = Math.trunc(rem / dimX); const x = rem - y * dimX; if (x > 0) tail = tryEnqueueRegionNeighbor(index - 1, mask, queue, tail, voxelData, minHU, maxHU, gateMask); if (x < dimX - 1) tail = tryEnqueueRegionNeighbor(index + 1, mask, queue, tail, voxelData, minHU, maxHU, gateMask); if (y > 0) tail = tryEnqueueRegionNeighbor(index - dimX, mask, queue, tail, voxelData, minHU, maxHU, gateMask); if (y < dimY - 1) tail = tryEnqueueRegionNeighbor(index + dimX, mask, queue, tail, voxelData, minHU, maxHU, gateMask); if (z > 0) tail = tryEnqueueRegionNeighbor(index - dimXY, mask, queue, tail, voxelData, minHU, maxHU, gateMask); if (z < dimZ - 1) tail = tryEnqueueRegionNeighbor(index + dimXY, mask, queue, tail, voxelData, minHU, maxHU, gateMask); } return mask; } /** Converts Float32 voxel data to a Uint8 binary mask: 1 where HU is in [minHU, maxHU], 0 elsewhere. */ function computeThresholdMask(voxelData, minHU, maxHU, out) { const result = out ?? new Uint8Array(voxelData.length); // eslint-disable-next-line unicorn/no-for-loop for (let index = 0; index < voxelData.length; index++) { const hu = voxelData[index]; result[index] = hu >= minHU && hu <= maxHU ? 1 : 0; } return result; } const AUTO_THRESHOLD_SAMPLE_TARGET = 300_000; const AUTO_THRESHOLD_WINDOW_MIN_HU = 100; const AUTO_THRESHOLD_WINDOW_MAX_HU = 1500; const AUTO_THRESHOLD_SHOULDER_FRACTION = 0.15; // Calcium's histogram tail decays more gradually than the blood peak's low side, so // walking out at the same 15% cutoff overshoots into it. A stricter cutoff on the // right pulls bloodCalciumThreshold back down closer to the peak. const AUTO_THRESHOLD_RIGHT_SHOULDER_FRACTION = 0.3; const AUTO_THRESHOLD_MIN_SPAN = 80; const AUTO_THRESHOLD_MIN_PEAK_COUNT = 20; /** Strided single-pass histogram over [windowMin, windowMax] at 1-HU resolution. */ function buildStridedHistogramInWindow(voxelData, windowMin, windowMax) { const histogram = new Int32Array(windowMax - windowMin + 1); const stride = Math.max(1, Math.floor(voxelData.length / AUTO_THRESHOLD_SAMPLE_TARGET)); for (let index = 0; index < voxelData.length; index += stride) { const hu = voxelData[index]; if (hu < windowMin || hu > windowMax) continue; const bucket = Math.trunc(hu) - windowMin; histogram[bucket] = histogram[bucket] + 1; } return histogram; } /** The tallest bucket in the histogram, or peakBucket=-1 if every bucket is empty. */ function findPeakBucket(histogram) { let peakBucket = -1; let peakCount = 0; for (const [bucket, count] of histogram.entries()) { if (count > peakCount) { peakCount = count; peakBucket = bucket; } } return { peakBucket, peakCount }; } /** Walks outward from the peak until the count drops below each side's own fraction * of the peak height — separate fractions since the two tails decay differently. */ function findShoulders(histogram, peakBucket, peakCount, leftFraction, rightFraction) { const leftShoulderCount = peakCount * leftFraction; const rightShoulderCount = peakCount * rightFraction; let leftBucket = peakBucket; while (leftBucket > 0 && histogram[leftBucket - 1] >= leftShoulderCount) { leftBucket--; } let rightBucket = peakBucket; while (rightBucket < histogram.length - 1 && histogram[rightBucket + 1] >= rightShoulderCount) { rightBucket++; } return { leftBucket, rightBucket }; } /** * Estimates a per-scan (tissueBloodThreshold, bloodCalciumThreshold) pair from * a strided sample of the volume's HU histogram: finds the dominant peak * within a plausible contrast-enhanced-blood window and walks outward to its * shoulders. A heuristic starting point, not a guaranteed-correct one — * returns undefined when the histogram is too sparse/flat to trust. */ function computeAutoVascularThresholds(voxelData) { const windowMin = AUTO_THRESHOLD_WINDOW_MIN_HU; const windowMax = AUTO_THRESHOLD_WINDOW_MAX_HU; const histogram = buildStridedHistogramInWindow(voxelData, windowMin, windowMax); const { peakBucket, peakCount } = findPeakBucket(histogram); if (peakBucket === -1 || peakCount < AUTO_THRESHOLD_MIN_PEAK_COUNT) return undefined; const { leftBucket, rightBucket } = findShoulders(histogram, peakBucket, peakCount, AUTO_THRESHOLD_SHOULDER_FRACTION, AUTO_THRESHOLD_RIGHT_SHOULDER_FRACTION); const tissueBloodThreshold = windowMin + leftBucket; const bloodCalciumThreshold = windowMin + rightBucket; if (bloodCalciumThreshold - tissueBloodThreshold < AUTO_THRESHOLD_MIN_SPAN) return undefined; return { bloodCalciumThreshold, tissueBloodThreshold }; } /** Single pass over the voxels matching targetLabel, gathering their HU range and count. */ function computeMaskedRangeAndCount(voxelData, labels, targetLabel) { let min = Infinity; let max = -Infinity; let count = 0; for (const [index, label] of labels.entries()) { if (label !== targetLabel) continue; const hu = voxelData[index]; if (hu < min) min = hu; if (hu > max) max = hu; count++; } return { count, max, min }; } /** Histogram of just the voxels matching targetLabel, bucketed across [min, max]. */ function buildMaskedHistogram(voxelData, labels, targetLabel, min, binWidth, bucketCount) { const histogram = new Int32Array(bucketCount); for (const [index, label] of labels.entries()) { if (label !== targetLabel) continue; const hu = voxelData[index]; const bucket = Math.min(bucketCount - 1, Math.max(0, Math.trunc((hu - min) / binWidth))); histogram[bucket] = histogram[bucket] + 1; } return histogram; } /** The HU value (bucket left-edge) at which the running count first reaches `target`. */ function percentileFromHistogram(histogram, target, min, binWidth, fallback) { let running = 0; for (const [bucket, value] of histogram.entries()) { running += value; if (running >= target) return min + bucket * binWidth; } return fallback; } /** * Reads off the [lowPercentile, highPercentile] HU range of the voxels whose * label matches targetLabel — used to tighten the auto-thresholds once an * exact segmentation mask exists. Returns undefined when no voxels match. */ function computePercentileRange(voxelData, labels, targetLabel, lowPercentile, highPercentile) { const { count, max, min } = computeMaskedRangeAndCount(voxelData, labels, targetLabel); if (count === 0 || !Number.isFinite(min) || !Number.isFinite(max) || min === max) { return undefined; } const bucketCount = Math.min(2000, Math.max(1, Math.ceil(max - min) + 1)); const binWidth = (max - min) / bucketCount; const histogram = buildMaskedHistogram(voxelData, labels, targetLabel, min, binWidth, bucketCount); const low = percentileFromHistogram(histogram, count * (lowPercentile / 100), min, binWidth, min); const high = percentileFromHistogram(histogram, count * (highPercentile / 100), min, binWidth, max); if (high <= low) return undefined; return { high: Math.round(high), low: Math.round(low) }; } /** Returns true if the mask is set at ±r along the X axis. */ function erosionXAxisPasses(mask, index, x, dimX, r) { if (x < r || !mask[index - r]) return false; if (x + r >= dimX || !mask[index + r]) return false; return true; } /** Returns true if the mask is set at ±r along the Y axis. */ function erosionYAxisPasses(mask, index, y, dimY, dimX, r) { if (y < r || !mask[index - r * dimX]) return false; if (y + r >= dimY || !mask[index + r * dimX]) return false; return true; } /** Returns true if the mask is set at ±r along the Z axis. */ function erosionZAxisPasses(mask, index, z, dimZ, dimXY, r) { if (z < r || !mask[index - r * dimXY]) return false; if (z + r >= dimZ || !mask[index + r * dimXY]) return false; return true; } /** Returns true if all 6-axis neighbors within radius are set in the mask. */ function voxelSurvivesErosion(mask, index, x, y, z, dimX, dimY, dimZ, dimXY, radius) { for (let r = 1; r <= radius; r++) { if (!erosionXAxisPasses(mask, index, x, dimX, r)) return false; if (!erosionYAxisPasses(mask, index, y, dimY, dimX, r)) return false; if (!erosionZAxisPasses(mask, index, z, dimZ, dimXY, r)) return false; } return true; } /** Erodes a binary Uint8 mask by radius using a 6-axis cross-shaped structuring element. */ function erodeBinaryMask(mask, dimensions, radius, out) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const size = dimXY * dimZ; const result = out ?? new Uint8Array(size); for (let index = 0; index < size; index++) { if (!mask[index]) continue; const z = Math.trunc(index / dimXY); const rem = index - z * dimXY; const y = Math.trunc(rem / dimX); const x = rem - y * dimX; if (voxelSurvivesErosion(mask, index, x, y, z, dimX, dimY, dimZ, dimXY, radius)) result[index] = 1; } return result; } /** Sets neighborIndex in result if passable and not already marked. */ function tryMarkDilated(neighborIndex, result, passableMask) { if (!result[neighborIndex] && passableMask[neighborIndex]) result[neighborIndex] = 1; } /** Spreads dilation from index outward by up to radius steps along all 6 axes. */ function dilateVoxelNeighbors(index, result, passableMask, x, y, z, dimX, dimY, dimZ, dimXY, radius) { for (let r = 1; r <= radius; r++) { if (x >= r) tryMarkDilated(index - r, result, passableMask); if (x + r < dimX) tryMarkDilated(index + r, result, passableMask); if (y >= r) tryMarkDilated(index - r * dimX, result, passableMask); if (y + r < dimY) tryMarkDilated(index + r * dimX, result, passableMask); if (z >= r) tryMarkDilated(index - r * dimXY, result, passableMask); if (z + r < dimZ) tryMarkDilated(index + r * dimXY, result, passableMask); } } /** Dilates a binary mask by radius, constrained to the passable region. */ function dilateMask(mask, passableMask, dimensions, radius, out) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const size = dimXY * dimZ; const result = out ?? new Uint8Array(size); for (let index = 0; index < size; index++) { if (!mask[index]) continue; result[index] = 1; const z = Math.trunc(index / dimXY); const rem = index - z * dimXY; const y = Math.trunc(rem / dimX); const x = rem - y * dimX; dilateVoxelNeighbors(index, result, passableMask, x, y, z, dimX, dimY, dimZ, dimXY, radius); } return result; } /** Enqueues a component neighbor if unvisited and set in mask. Returns the updated tail. */ function tryEnqueueComponentNeighbor(ni, mask, visited, queue, tail) { if (!visited[ni] && mask[ni]) { visited[ni] = 1; queue[tail] = ni; return tail + 1; } return tail; } /** BFS collecting all voxel indices in the 6-connected component starting at startIndex. * Returns the component length; indices are stored in queue[0..length-1]. */ function bfsComponent(startIndex, mask, visited, queue, dimX, dimY, dimZ, dimXY) { visited[startIndex] = 1; queue[0] = startIndex; let head = 0; let tail = 1; while (head < tail) { const index = queue[head++]; const z = Math.trunc(index / dimXY); const rem = index - z * dimXY; const y = Math.trunc(rem / dimX); const x = rem - y * dimX; if (x > 0) tail = tryEnqueueComponentNeighbor(index - 1, mask, visited, queue, tail); if (x < dimX - 1) tail = tryEnqueueComponentNeighbor(index + 1, mask, visited, queue, tail); if (y > 0) tail = tryEnqueueComponentNeighbor(index - dimX, mask, visited, queue, tail); if (y < dimY - 1) tail = tryEnqueueComponentNeighbor(index + dimX, mask, visited, queue, tail); if (z > 0) tail = tryEnqueueComponentNeighbor(index - dimXY, mask, visited, queue, tail); if (z < dimZ - 1) tail = tryEnqueueComponentNeighbor(index + dimXY, mask, visited, queue, tail); } return tail; } /** First-pass BFS to rank components by size, then re-BFS top N to mark result. */ function pruneKeepLargestN(mask, visited, result, queue, dimX, dimY, dimZ, dimXY, minSize, maxComponents) { const survivors = []; for (let startIndex = 0; startIndex < mask.length; startIndex++) { if (!mask[startIndex] || visited[startIndex]) continue; const length = bfsComponent(startIndex, mask, visited, queue, dimX, dimY, dimZ, dimXY); if (length >= minSize) survivors.push([startIndex, length]); } survivors.sort((a, b) => b[1] - a[1]); survivors.length = Math.min(survivors.length, maxComponents); visited.fill(0); for (const [startIndex] of survivors) { const length = bfsComponent(startIndex, mask, visited, queue, dimX, dimY, dimZ, dimXY); for (let index = 0; index < length; index++) result[queue[index]] = 1; } } /** Removes components smaller than minSize; when maxComponents is set, keeps only the largest N. */ function pruneSmallClusters(mask, dimensions, minSize = MIN_CLUSTER_SIZE, scratchVisited, out, maxComponents, scratchQueue) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const visited = scratchVisited ?? new Uint8Array(mask.length); const result = out ?? new Uint8Array(mask.length); const queue = scratchQueue ?? new Int32Array(mask.length); if (maxComponents !== undefined) { pruneKeepLargestN(mask, visited, result, queue, dimX, dimY, dimZ, dimXY, minSize, maxComponents); return result; } for (let startIndex = 0; startIndex < mask.length; startIndex++) { if (!mask[startIndex] || visited[startIndex]) continue; const length = bfsComponent(startIndex, mask, visited, queue, dimX, dimY, dimZ, dimXY); if (length >= minSize) { for (let index = 0; index < length; index++) result[queue[index]] = 1; } } return result; } /** Marks voxels within [minHU, maxHU] that are absent from the connected mask (disconnected fragments). */ function buildOutlierMask(voxelData, connectedMask, minHU, maxHU, out) { const outlier = out ?? new Uint8Array(voxelData.length); // eslint-disable-next-line unicorn/no-for-loop for (let index = 0; index < connectedMask.length; index++) { if (!connectedMask[index]) { const hu = voxelData[index]; if (hu >= minHU && hu <= maxHU) outlier[index] = 1; } } return outlier; } /** Stride-samples the volume by PREVIEW_DOWNSAMPLE per axis. */ function downsampleVolume(voxelData, dimensions) { const [dimX, dimY, dimZ] = dimensions; const dimXY = dimX * dimY; const outX = Math.ceil(dimX / PREVIEW_DOWNSAMPLE); const outY = Math.ceil(dimY / PREVIEW_DOWNSAMPLE); const outZ = Math.ceil(dimZ / PREVIEW_DOWNSAMPLE); const out = new Float32Array(outX * outY * outZ); let write = 0; for (let z = 0; z < outZ; z++) { const sliceBase = z * PREVIEW_DOWNSAMPLE * dimXY; for (let y = 0; y < outY; y++) { const rowBase = sliceBase + y * PREVIEW_DOWNSAMPLE * dimX; for (let x = 0; x < outX; x++) { out[write++] = voxelData[rowBase + x * PREVIEW_DOWNSAMPLE]; } } } return { dimensions: [outX, outY, outZ], voxelData: out }; } /** Nearest-neighbour upsample of preview labels to full dims, so the GPU * mask contract (labels match the CT voxel count) holds for preview runs. */ function upsampleLabelMask(labels, previewDimensions, fullDimensions) { const [previewX, previewY, previewZ] = previewDimensions; const [fullX, fullY, fullZ] = fullDimensions; const out = new Uint8Array(fullX * fullY * fullZ); // Per-axis source maps hoist the divide + clamp out of the hot loop. const sourceX = new Int32Array(fullX); for (let x = 0; x < fullX; x++) { sourceX[x] = Math.min(Math.trunc(x / PREVIEW_DOWNSAMPLE), previewX - 1); } let write = 0; for (let z = 0; z < fullZ; z++) { const sourceZ = Math.min(Math.trunc(z / PREVIEW_DOWNSAMPLE), previewZ - 1); for (let y = 0; y < fullY; y++) { const sourceY = Math.min(Math.trunc(y / PREVIEW_DOWNSAMPLE), previewY - 1); const sourceRow = (sourceZ * previewY + sourceY) * previewX; for (let x = 0; x < fullX; x++) { out[write++] = labels[sourceRow + sourceX[x]]; } } } return out; } /** Baked into the mask shader's label decode — the component-1 TF range is * pinned to [0, outlier]. */ const VASCULAR_MASK_LABELS = { background: 0, outlier: 2, vessel: 1 }; /** vessel = connected ∪ (pruned-outlier ∩ dilated-restore), outlier = the * rest of pruned-outlier, background = everything else. Writes every index * of the output, whose length bounds the loop — worker scratch inputs may * be longer than the volume. */ function buildLabelMask(connectedMask, prunedOutlierMask, dilatedMask, out) { const labels = out ?? new Uint8Array(connectedMask.length); for (let index = 0; index < labels.length; index++) { if (connectedMask[index]) { labels[index] = VASCULAR_MASK_LABELS.vessel; } else if (prunedOutlierMask[index]) { labels[index] = dilatedMask?.[index] ? VASCULAR_MASK_LABELS.vessel : VASCULAR_MASK_LABELS.outlier; } else { labels[index] = VASCULAR_MASK_LABELS.background; } } return labels; } // ── Main-thread helpers ─────────────────────────────────────────────────────── // The exports below depend on browser globals (Worker) and must NOT be called // from within vascular-mask.worker.ts. /** Shared state for the worker request/response cycle — mutated by both getVascularWorker and applyVascularRegionMask. */ const vascularRequestState = { /** Newest request id per worker kind. Staleness is judged within a kind — * a live preview tick must not invalidate an in-flight exact run. */ latestIds: { full: -1, preview: -1 }, nextId: 0, pending: new Map(), /** volumeKey each worker holds resident; undefined after terminate/error, * which tells the next request to include the voxel buffer. */ workerVolumeKeys: { full: undefined, preview: undefined } }; /***/ }, /***/ 31351 /*!*******************************************************************!*\ !*** ./libs/utils/src/lib/segmentation/vascular-worker-helper.ts ***! \*******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cancelPendingVascularRequests: () => (/* binding */ cancelPendingVascularRequests), /* harmony export */ getVascularWorker: () => (/* binding */ getVascularWorker), /* harmony export */ releaseVascularWorkers: () => (/* binding */ releaseVascularWorkers) /* harmony export */ }); /* harmony import */ var _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./vascular-mask-compute */ 72024); // Two isolated workers, same script: 'full' for exact runs, 'preview' for // live slider ticks. A grinding full run never blocks or evicts the preview path. const _workers = {}; /** Rejects the kind's in-flight requests and terminates its worker — dropping * its resident volume, so the next request must resend the buffer. */ function cancelPendingVascularRequests(kind = 'full') { let rejected = false; for (const [requestId, pending] of _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending) { if (pending.kind !== kind) continue; pending.reject(new Error('superseded')); _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.delete(requestId); rejected = true; } if (!rejected) return; _workers[kind]?.terminate(); _workers[kind] = undefined; _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.workerVolumeKeys[kind] = undefined; } /** For series/study teardown — a live worker would keep the previous volume's * ~400 MB resident indefinitely. */ function releaseVascularWorkers() { for (const pending of _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.values()) { pending.reject(new Error('released')); } _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.clear(); for (const kind of ['full', 'preview']) { _workers[kind]?.terminate(); _workers[kind] = undefined; _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.workerVolumeKeys[kind] = undefined; } } function getVascularWorker(kind = 'full') { let worker = _workers[kind]; if (!worker) { worker = new Worker(__webpack_require__.tu(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("libs_utils_src_lib_segmentation_vascular-mask_worker_ts"), __webpack_require__.b))); worker.addEventListener('message', ({ data }) => { const pending = _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.get(data.requestId); if (!pending) return; _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.delete(data.requestId); pending.resolve(data); }); worker.addEventListener('error', event => { for (const [requestId, pending] of _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending) { if (pending.kind !== kind) continue; pending.reject(event); _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.pending.delete(requestId); } _workers[kind] = undefined; _vascular_mask_compute__WEBPACK_IMPORTED_MODULE_0__.vascularRequestState.workerVolumeKeys[kind] = undefined; }); _workers[kind] = worker; } return worker; } /***/ }, /***/ 84736 /*!***************************************!*\ !*** ./libs/utils/src/lib/signals.ts ***! \***************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ computeThrottled: () => (/* binding */ computeThrottled), /* harmony export */ lastDefined: () => (/* binding */ lastDefined) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 39231); /* harmony import */ var _throttle_debounce__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./throttle-debounce */ 30245); /** * A variation of `compute()` that will apply a throttle (with trailing) before setting * the state value. This will not prevent the compute function from running * on every change, so this is mainly beneficial if there is an expensive * calculation downstream from this value. * * @param function_ * @param waitMs * @returns */ function computeThrottled(function_, waitMs) { const state = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.signal)(function_(), ...(ngDevMode ? [{ debugName: "state" }] : [])); const setter = (0,_throttle_debounce__WEBPACK_IMPORTED_MODULE_2__.throttleTrailing)(value => state.set(value), waitMs); (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.effect)(() => { const result = function_(); setter(result); }); return state.asReadonly(); } /** * Returns a linkedSignal that holds on the latest non-undefined value in the source signal, * until it is manually reset. */ function lastDefined(source) { return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.linkedSignal)({ computation: (current, previous) => current ?? previous?.value, source: () => source() }); } /***/ }, /***/ 1331 /*!***********************************!*\ !*** ./libs/utils/src/lib/svg.ts ***! \***********************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildSvgPath: () => (/* binding */ buildSvgPath) /* harmony export */ }); function buildSvgPath(points) { let start = true; return points.map(([x, y]) => { if (start) { start = false; return `M${x} ${y}`; } return `L${x} ${y}`; }).join(' '); } /***/ }, /***/ 30245 /*!*************************************************!*\ !*** ./libs/utils/src/lib/throttle-debounce.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ debounce: () => (/* binding */ debounce), /* harmony export */ throttle: () => (/* binding */ throttle), /* harmony export */ throttleTrailing: () => (/* binding */ throttleTrailing) /* harmony export */ }); /** * Basic throttling implementation that will provide a return value. */ function throttle(function_, intervalMs) { let lastCall = 0; let lastValue; return (...arguments_) => { const now = performance.now(); if (now - lastCall >= intervalMs) { lastCall = now; lastValue = function_(...arguments_); } return lastValue; }; } /** * Throttling implementation that will make a trailing call * once the timeout completes, like a built-in debounce. * As part of this implementation, there are no return values. */ function throttleTrailing(function_, intervalMs) { let lastCall = 0; let trailingTimer; return (...arguments_) => { const now = performance.now(); const remaining = intervalMs - (now - lastCall); if (trailingTimer) { clearTimeout(trailingTimer); trailingTimer = undefined; } if (remaining <= 0) { lastCall = now; function_(...arguments_); } else { trailingTimer = setTimeout(() => { lastCall = performance.now(); trailingTimer = undefined; function_(...arguments_); }, remaining); } }; } /** * Debounce with no return value. Trailing by default: invokes once intervalMs * passes without any call. With leading set, invokes immediately on the first * call of a burst instead, then suppresses until the burst ends. */ function debounce(function_, intervalMs, leading = false) { let timer; return (...arguments_) => { if (timer === undefined) { if (leading) function_(...arguments_); } else { clearTimeout(timer); } timer = setTimeout(() => { timer = undefined; if (!leading) function_(...arguments_); }, intervalMs); }; } /***/ }, /***/ 35498 /*!*************************************************!*\ !*** ./libs/utils/src/lib/translate-handler.ts ***! \*************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ translate: () => (/* binding */ translate) /* harmony export */ }); /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 40072); /* harmony import */ var _ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @ngx-translate/core */ 96110); class TranslateHandler { translateService = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_ngx_translate_core__WEBPACK_IMPORTED_MODULE_1__.TranslateService); translate(key) { return this.translateService.instant(key); } } /** * Translates a given key using Angular's TranslateService. * * @param {string} key - The translation key to look up. * @returns {string} The translated string for the current language. * * @throws Will throw if called outside of an Angular injection context. * * @example * // Returns the translation for 'home.title' * const title = translate('home.title'); */ const translate = key => { return new TranslateHandler().translate(key); }; /***/ }, /***/ 29324 /*!***********************************************************************!*\ !*** ./libs/utils/src/lib/volume-viewer/build-series-window-state.ts ***! \***********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ buildSeriesWindowState: () => (/* binding */ buildSeriesWindowState) /* harmony export */ }); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ 11280); /* harmony import */ var _dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../dicom/windowing-presets */ 21423); const buildSeriesWindowState = (windowMetadata, defaultWindowPreset, defaultMaxPixelSize) => { const widthPresets = windowMetadata.windowWidths ?? [windowMetadata.windowWidth ?? defaultWindowPreset.width]; const levelPresets = windowMetadata.windowLevels ?? [windowMetadata.windowLevel ?? defaultWindowPreset.level]; const dicomPresets = (0,_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_1__.buildDicomPresets)(widthPresets, levelPresets, _constants__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_PRESET_NAME); const windowPresets = [...dicomPresets, ..._dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_1__.BASE_MPR_WL_PRESETS]; return { ...(0,_dicom_windowing_presets__WEBPACK_IMPORTED_MODULE_1__.buildWindowDefaults)(defaultWindowPreset, dicomPresets[0]), defaultMaxPixelSize, metadata: windowMetadata, windowPresets }; }; /***/ }, /***/ 34417 /*!******************************************************************!*\ !*** ./libs/utils/src/lib/volume-viewer/camera-interpolation.ts ***! \******************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ cameraStateAtProgress: () => (/* binding */ cameraStateAtProgress) /* harmony export */ }); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! gl-matrix */ 23988); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ 85648); /* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! gl-matrix */ 87396); /* harmony import */ var _position__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../position */ 60174); /** * Interpolate between two camera states at progress `t` in `[0, 1]`. */ function cameraStateAtProgress(start, target, t) { const intersection = (0,_position__WEBPACK_IMPORTED_MODULE_3__.vec3ToPosition)(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.lerp(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), (0,_position__WEBPACK_IMPORTED_MODULE_3__.positionToVec3)(start.intersection), (0,_position__WEBPACK_IMPORTED_MODULE_3__.positionToVec3)(target.intersection), t)); const isocenter = (0,_position__WEBPACK_IMPORTED_MODULE_3__.vec3ToPosition)(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.lerp(gl_matrix__WEBPACK_IMPORTED_MODULE_2__.create(), (0,_position__WEBPACK_IMPORTED_MODULE_3__.positionToVec3)(start.isocenter), (0,_position__WEBPACK_IMPORTED_MODULE_3__.positionToVec3)(target.isocenter), t)); if (!target.matrix || !start.matrix) { return { intersection, isocenter }; } const from = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromMat3(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), start.matrix)); const to = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_1__.fromMat3(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), target.matrix)); // Take the shortest arc if (gl_matrix__WEBPACK_IMPORTED_MODULE_1__.dot(from, to) < 0) { gl_matrix__WEBPACK_IMPORTED_MODULE_1__.scale(to, to, -1); } const interpolated = gl_matrix__WEBPACK_IMPORTED_MODULE_1__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_1__.slerp(gl_matrix__WEBPACK_IMPORTED_MODULE_1__.create(), from, to, t)); return { intersection, isocenter, matrix: gl_matrix__WEBPACK_IMPORTED_MODULE_0__.fromQuat(gl_matrix__WEBPACK_IMPORTED_MODULE_0__.create(), interpolated) }; } /***/ }, /***/ 30050 /*!*********************************************************************!*\ !*** ./libs/utils/src/lib/volume-viewer/default-viewport-config.ts ***! \*********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getDefaultViewport: () => (/* binding */ getDefaultViewport) /* harmony export */ }); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ 11280); const getDefaultViewport = options => { return { ..._constants__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_VIEWPORT_CONFIG, ...options, isInitialized: false }; }; /***/ }, /***/ 3009 /*!*************************************************************************!*\ !*** ./libs/utils/src/lib/volume-viewer/map-viewport-to-orientation.ts ***! \*************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ mapViewportIdToOrientation: () => (/* binding */ mapViewportIdToOrientation) /* harmony export */ }); /* harmony import */ var _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tomoverse/enums */ 66556); const mapViewportIdToOrientation = id => { switch (id) { case 'viewportAxial': { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.OrientationAxis.AXIAL; } case 'viewportCoronal': { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.OrientationAxis.CORONAL; } case 'viewportSagittal': { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.OrientationAxis.SAGITTAL; } default: { return _tomoverse_enums__WEBPACK_IMPORTED_MODULE_0__.OrientationAxis.ACQUISITION; } } }; /***/ }, /***/ 60579 /*!*******************************************!*\ !*** ./libs/utils/src/lib/vtk/mappers.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ annotationMapper: () => (/* binding */ annotationMapper) /* harmony export */ }); /* harmony import */ var _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @kitware/vtk.js/Rendering/Core/Mapper */ 55857); /** * Return a * @returns */ function annotationMapper(source) { const mapper = _kitware_vtk_js_Rendering_Core_Mapper__WEBPACK_IMPORTED_MODULE_0__["default"].newInstance(); mapper.setResolveCoincidentTopologyToPolygonOffset(); if (source) { mapper.setInputConnection(source.getOutputPort()); } return mapper; } /***/ }, /***/ 2951 /*!*******************************************!*\ !*** ./libs/utils/src/lib/vtk/shaders.ts ***! \*******************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ fragmentReplacement: () => (/* binding */ fragmentReplacement), /* harmony export */ removeShaderCallback: () => (/* binding */ removeShaderCallback), /* harmony export */ removeShaderReplacement: () => (/* binding */ removeShaderReplacement), /* harmony export */ setShaderCallback: () => (/* binding */ setShaderCallback), /* harmony export */ setShaderReplacement: () => (/* binding */ setShaderReplacement), /* harmony export */ vertexReplacement: () => (/* binding */ vertexReplacement) /* harmony export */ }); // Keyed registry over VTK's per-mapper `ShaderReplacements` and // `ShadersCallbacks` arrays, so multiple features can patch the same mapper // without overwriting each other. /** Builds a Fragment-stage replacement. */ function fragmentReplacement(originalValue, replacementValue, options = {}) { return { originalValue, replaceAll: options.replaceAll ?? false, replaceFirst: options.replaceFirst ?? false, replacementValue, shaderType: 'Fragment' }; } /** Builds a Vertex-stage replacement. */ function vertexReplacement(originalValue, replacementValue, options = {}) { return { originalValue, replaceAll: options.replaceAll ?? false, replaceFirst: options.replaceFirst ?? false, replacementValue, shaderType: 'Vertex' }; } /** * Installs entries for `feature` on the mapper. Skips the write when the * new entries deep-equal the existing ones to avoid a GLSL recompile. */ function setShaderReplacement(mapper, feature, replacements) { const openGL = getOpenGLProperties(mapper); if (!openGL) return; const array = openGL.ShaderReplacements ?? []; const desired = (Array.isArray(replacements) ? replacements : [replacements]).map(r => ({ ...r, __feature: feature })); const [existing, others] = partitionByFeature(array, feature); if (replacementsEqual(existing, desired)) return; // Assign a NEW array so VTK's previousState reference diverges from currentState, // causing DeepEqual to detect the change and trigger a shader recompile. openGL.ShaderReplacements = [...others, ...desired]; mapper.modified(); } /** Removes entries owned by `feature` from the mapper, leaving other features untouched. */ function removeShaderReplacement(mapper, feature) { const openGL = getOpenGLProperties(mapper); if (!openGL) return; const array = openGL.ShaderReplacements ?? []; const kept = array.filter(r => r.__feature !== feature); if (kept.length === array.length) return; openGL.ShaderReplacements = kept; mapper.modified(); } /** * Installs a per-draw uniform-pushing callback for `feature`. Idempotent — * if a callback is already registered for the same feature, the call is a * no-op (callbacks close over feature-owned state, so re-registering would * just stack identical work on every draw). */ function setShaderCallback(mapper, feature, callback) { const array = getShaderCallbacks(mapper); if (!array) return; if (array.some(c => c.__feature === feature)) return; array.push({ ...callback, __feature: feature }); } /** Removes any callback owned by `feature` from the mapper. */ function removeShaderCallback(mapper, feature) { const array = getShaderCallbacks(mapper); if (!array) return; const kept = array.filter(c => c.__feature !== feature); if (kept.length === array.length) return; array.length = 0; array.push(...kept); } function getOpenGLProperties(mapper) { const properties = mapper.getViewSpecificProperties?.(); if (!properties) return undefined; properties.OpenGL ??= {}; return properties.OpenGL; } function getShaderCallbacks(mapper) { const properties = mapper.getViewSpecificProperties?.(); if (!properties) return undefined; properties.ShadersCallbacks ??= []; return properties.ShadersCallbacks; } function partitionByFeature(array, feature) { const owned = []; const others = []; for (const r of array) (r.__feature === feature ? owned : others).push(r); return [owned, others]; } function replacementsEqual(a, b) { if (a.length !== b.length) return false; return a.every((x, index) => { const y = b[index]; return x.originalValue === y.originalValue && x.replacementValue === y.replacementValue && x.shaderType === y.shaderType && x.replaceAll === y.replaceAll && x.replaceFirst === y.replaceFirst; }); } /***/ }, /***/ 85444 /*!***************************************************!*\ !*** ./libs/utils/src/lib/vtk/strips-to-polys.ts ***! \***************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ stripsToPolys: () => (/* binding */ stripsToPolys) /* harmony export */ }); // `vtkTubeFilter` outputs Triangle Strips instead of Polys, // but `vtkCellPicker` cannot detect Triangle Strips. // This converts the strips into polys so that the picker works. function stripsToPolys(polyData) { const strips = polyData.getStrips().getData(); const polys = []; // If this was already converted, running it again effectively clears everything if (polyData.getNumberOfPolys() > 0) return; let i = 0; while (i < strips.length) { const npts = strips[i++]; for (let j = 0; j < npts - 2; j++) { polys.push(3); // Triangle cell size if (j % 2 === 0) { polys.push(strips[i + j], strips[i + j + 1], strips[i + j + 2]); } else { polys.push(strips[i + j + 1], strips[i + j], strips[i + j + 2]); } } i += npts; } polyData.getPolys().setData(Uint32Array.from(polys)); polyData.getStrips().setData([]); polyData.getPolys().modified(); polyData.getStrips().modified(); polyData.modified(); } /***/ }, /***/ 77931 /*!*********************************************!*\ !*** ./libs/utils/src/lib/webgl/program.ts ***! \*********************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ compileShader: () => (/* binding */ compileShader), /* harmony export */ linkProgram: () => (/* binding */ linkProgram) /* harmony export */ }); // Generic WebGL2 shader-program helpers. No vtk.js / post-process knowledge. /** Compile a vertex/fragment program. Throws on any failure. */ function compileShader(gl, type, source, label = 'compileShader') { const shader = gl.createShader(type); if (!shader) throw new Error(`${label}: failed to create shader`); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { const log = gl.getShaderInfoLog(shader); gl.deleteShader(shader); throw new Error(`${label}: shader compile failed: ${log}`); } return shader; } /** Compile and link a vertex/fragment program. Throws on any failure. */ function linkProgram(gl, vertSource, fragSource, label = 'linkProgram') { const program = gl.createProgram(); if (!program) throw new Error(`${label}: failed to create program`); const vs = compileShader(gl, gl.VERTEX_SHADER, vertSource, label); const fs = compileShader(gl, gl.FRAGMENT_SHADER, fragSource, label); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); gl.deleteShader(vs); gl.deleteShader(fs); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { const log = gl.getProgramInfoLog(program); gl.deleteProgram(program); throw new Error(`${label}: program link failed: ${log}`); } return program; } /***/ }, /***/ 68105 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/shaders/annotation-fade-decl.frag.glsl ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("uniform float uFadeVisibleDistance;\nuniform float uFadeSelectedAlpha;\nuniform int uFadeEnabled;\nuniform int uFadeSelected;\nin float vFadeSignedDistance;"); /***/ }, /***/ 22926 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/shaders/annotation-fade-decl.vert.glsl ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("uniform mat4 MCVCMatrix;\nuniform float uFadeCameraToPlaneDistance;\nout float vFadeSignedDistance;"); /***/ }, /***/ 50927 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/shaders/annotation-fade-impl.frag.glsl ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("if (uFadeEnabled == 1) {\n float absDist = abs(vFadeSignedDistance);\n float alphaFloor = uFadeSelected == 1 ? uFadeSelectedAlpha : 0.0;\n float fadeAlpha = absDist < uFadeVisibleDistance\n ? 1.0 - (absDist / uFadeVisibleDistance) * (1.0 - alphaFloor)\n : alphaFloor;\n gl_FragData[0].a *= fadeAlpha;\n}"); /***/ }, /***/ 6504 /*!*****************************************************************************************************!*\ !*** ./libs/feature/src/lib/volume-viewer/annotation-actors/shaders/annotation-fade-impl.vert.glsl ***! \*****************************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("vec4 vertexVCFade = MCVCMatrix * vertexMC;\nvFadeSignedDistance = vertexVCFade.z + uFadeCameraToPlaneDistance;"); /***/ }, /***/ 92004 /*!**************************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/mask-preview/shaders/mask-preview.frag.glsl ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("#version 300 es\n\nprecision highp float;\n\nin vec2 vTexCoord;\nout vec4 fragOutput0;\n\nuniform sampler2D uMask;\nuniform vec2 uPreviewSizePx;\nuniform float uBorderPx;\nuniform vec3 uBorderColor;\n\nvoid main() {\n vec2 pxPos = vTexCoord * uPreviewSizePx;\n bool inBorder = pxPos.x < uBorderPx\n || pxPos.x > uPreviewSizePx.x - uBorderPx\n || pxPos.y < uBorderPx\n || pxPos.y > uPreviewSizePx.y - uBorderPx;\n if (inBorder) {\n fragOutput0 = vec4(uBorderColor, 1.0);\n return;\n }\n float v = texture(uMask, vTexCoord).a;\n fragOutput0 = vec4(v, v, v, 1.0);\n}"); /***/ }, /***/ 89084 /*!**************************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/shaders/outline-composite.frag.glsl ***! \**************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("#version 300 es\n\nprecision highp float;\n\nin vec2 vTexCoord;\nout vec4 fragOutput0;\n\nuniform sampler2D uMask;\nuniform vec2 uMaskSizePx;\nuniform float uOutlinePx;\n\nconst float kCloseRadiusPx = 0.0;\n\nvec4 maskAt(vec2 offsetPx) {\n vec2 uv = vTexCoord + offsetPx / uMaskSizePx;\n \n uv = clamp(uv, vec2(0.0), vec2(1.0));\n return texture(uMask, uv);\n}\n\nvec4 maxByAlpha(vec4 a, vec4 b) {\n return a.a >= b.a ? a : b;\n}\n\nvec4 dilatedAt(vec2 offsetPx) {\n float r = kCloseRadiusPx;\n float s = r * 0.70710678;\n vec4 m = maskAt(offsetPx);\n m = maxByAlpha(m, maskAt(offsetPx + vec2( r, 0.0)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2(-r, 0.0)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2( 0.0, r)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2( 0.0, -r)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2( s, s)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2(-s, s)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2( s, -s)));\n m = maxByAlpha(m, maskAt(offsetPx + vec2(-s, -s)));\n return m;\n}\n\nvoid main() {\n vec4 centre = dilatedAt(vec2(0.0));\n if (centre.a > 0.5) {\n \n discard;\n }\n\n \n float r = uOutlinePx;\n float s = r * 0.70710678; \n vec4 best = maxByAlpha(\n maxByAlpha(\n maxByAlpha(dilatedAt(vec2( r, 0.0)), dilatedAt(vec2(-r, 0.0))),\n maxByAlpha(dilatedAt(vec2( 0.0, r)), dilatedAt(vec2( 0.0, -r)))\n ),\n maxByAlpha(\n maxByAlpha(dilatedAt(vec2( s, s)), dilatedAt(vec2(-s, s))),\n maxByAlpha(dilatedAt(vec2( s, -s)), dilatedAt(vec2(-s, -s)))\n )\n );\n\n if (best.a < 0.5) {\n \n discard;\n }\n\n fragOutput0 = vec4(best.rgb / best.a, 1.0);\n}"); /***/ }, /***/ 92183 /*!*********************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/shaders/outline-mask.frag.glsl ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("#version 300 es\nprecision highp float;\n\nuniform vec3 uMaskColor;\n\nout vec4 fragOutput0;\n\nvoid main() {\n fragOutput0 = vec4(uMaskColor, 1.0);\n}"); /***/ }, /***/ 73200 /*!*********************************************************************************!*\ !*** ./libs/post-process/src/lib/passes/outline/shaders/outline-mask.vert.glsl ***! \*********************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("#version 300 es\n\nprecision highp float;\n\nin vec3 vertexMC;\nuniform mat4 MCDCMatrix;\n\nvoid main() {\n gl_Position = MCDCMatrix * vec4(vertexMC, 1.0);\n}"); /***/ }, /***/ 56053 /*!*******************************************************************************************!*\ !*** ./libs/post-process/src/lib/utils/fullscreen-quad/shaders/fullscreen-quad.vert.glsl ***! \*******************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("#version 300 es\n\nprecision highp float;\n\nout vec2 vTexCoord;\n\nvoid main() {\n float x = float((gl_VertexID & 1) << 1) - 1.0;\n float y = float(gl_VertexID & 2) - 1.0;\n vTexCoord = vec2((x + 1.0) * 0.5, (y + 1.0) * 0.5);\n gl_Position = vec4(x, y, 0.0, 1.0);\n}"); /***/ }, /***/ 79448 /*!********************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/shaders/clip-face.frag.glsl ***! \********************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("const float RAMP_LOOKAHEAD_VC = 0.1;\n \n \n const float OPAQUE_EPSILON = 0.001;\n \n \n \n const float TF_HEIGHT = 0.5;\n \n const int COMPONENT = 0;\n\n \n \n vec3 clipPosIS = posVCtoIS(firstPosVC);\n vec4 clipTexVal = getTextureValue(clipPosIS);\n float clipOpacity = getOpacityFromTexture(clipTexVal.r, COMPONENT, TF_HEIGHT);\n if (clipOpacity < OPAQUE_EPSILON) {\n vec3 aheadPosIS = posVCtoIS(firstPosVC + rayDirVC * RAMP_LOOKAHEAD_VC);\n vec4 aheadTexVal = getTextureValue(aheadPosIS);\n float aheadOpacity = getOpacityFromTexture(aheadTexVal.r, COMPONENT, TF_HEIGHT);\n if (aheadOpacity > OPAQUE_EPSILON) {\n clipTexVal = aheadTexVal;\n clipOpacity = aheadOpacity;\n }\n }\n if (clipOpacity > OPAQUE_EPSILON) {\n vec3 flatColor = getColorFromTexture(clipTexVal.r, COMPONENT, TF_HEIGHT);\n gl_FragData[0] = vec4(flatColor, 1.0);\n return;\n }\n vec4 color = vec4(firstColor.rgb * firstColor.a, firstColor.a);"); /***/ }, /***/ 11464 /*!*************************************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/shaders/two-sided-surface-lighting.frag.glsl ***! \*************************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("float ndotL = dot(normalVC.xyz, vertLightDirection);\n vec3 litNormal = normalVC.xyz;\n if (ndotL < 0.0) {\n ndotL = -ndotL;\n litNormal = -normalVC.xyz;\n }\n if (ndotL > 0.0) {\n \n \n const float WRAP = 0.7;\n diffuse += ((ndotL + WRAP) / (1.0 + WRAP)) * attenuation * lights[ligthIdx].color;\n \n \n float vdotR =\n dot(-rayDirVC, normalize(vertLightDirection - 2.0 * ndotL * litNormal));\n if (vdotR > 0.0)"); /***/ }, /***/ 63143 /*!************************************************************************!*\ !*** ./libs/utils/src/lib/cornerstone/shaders/vascular-mask.frag.glsl ***! \************************************************************************/ (__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("float maskLabel = 2.0 * (tValue[1] * volume.opacityTextureScale[1] +\n volume.opacityTextureShift[1]);\n\n \n \n float ctAlpha = getOpacityFromTexture(\n tValue[0], 0, volume.transferFunctionsSampleHeight[0]);\n\n#if VASCULAR_MASK_MODE == 2\n if (maskLabel < 0.5) {\n return vec4(0.0);\n }\n if (maskLabel > 1.5) {\n \n \n \n \n vec3 outlierColor = getColorFromTexture(\n tValue[0], 0, volume.transferFunctionsSampleHeight[0]);\n float outlierAlpha =\n getOpacityFromTexture(tValue[0], 0,\n volume.transferFunctionsSampleHeight[0]) *\n getOpacityFromTexture(tValue[1], 1,\n volume.transferFunctionsSampleHeight[1]);\n#if vtkNumberOfLights > 0\n vec3 outlierScalarInterp[2];\n vec4 outlierNormal0 = computeNormalForDensity(posIS, outlierScalarInterp, 0);\n vec4 outlierNormalLight = outlierNormal0;\n if (volume.computeNormalFromOpacity == 1 && outlierNormal0[3] != 0.0) {\n float outlierGradientOpacityFactor = computeGradientOpacityFactor(outlierNormal0.a, 0);\n outlierNormalLight = computeDensityNormal(\n outlierScalarInterp, volume.transferFunctionsSampleHeight[0],\n outlierGradientOpacityFactor, 0);\n if (outlierNormalLight[3] == 0.0) {\n outlierNormalLight = outlierNormal0;\n }\n }\n outlierColor = applyAllLightning(outlierColor, outlierAlpha, posVC, outlierNormalLight);\n#endif\n return vec4(outlierColor, outlierAlpha);\n }\n#endif\n\n#if VASCULAR_MASK_MODE == 1\n if (maskLabel > 0.5 && maskLabel < 1.5) {\n \n \n return vec4(\n getColorFromTexture(tValue[1], 1,\n volume.transferFunctionsSampleHeight[1]),\n getOpacityFromTexture(tValue[1], 1,\n volume.transferFunctionsSampleHeight[1]));\n }\n#endif\n\n if (ctAlpha < EPSILON) {\n return vec4(0.0);\n }\n\n \n \n vec3 ctColor = getColorFromTexture(\n tValue[0], 0, volume.transferFunctionsSampleHeight[0]);\n#if vtkNumberOfLights > 0\n vec3 scalarInterp[2];\n vec4 normal0 = computeNormalForDensity(posIS, scalarInterp, 0);\n vec4 normalLight = normal0;\n if (volume.computeNormalFromOpacity == 1 && normal0[3] != 0.0) {\n float gradientOpacityFactor = computeGradientOpacityFactor(normal0.a, 0);\n normalLight = computeDensityNormal(\n scalarInterp, volume.transferFunctionsSampleHeight[0],\n gradientOpacityFactor, 0);\n if (normalLight[3] == 0.0) {\n normalLight = normal0;\n }\n }\n ctColor = applyAllLightning(ctColor, ctAlpha, posVC, normalLight);\n#endif\n return vec4(ctColor, ctAlpha);"); /***/ }, /***/ 6221 /*!********************!*\ !*** fs (ignored) ***! \********************/ () { /* (ignored) */ /***/ }, /***/ 64150 /*!********************!*\ !*** fs (ignored) ***! \********************/ () { /* (ignored) */ /***/ }, /***/ 79696 /*!********************!*\ !*** fs (ignored) ***! \********************/ () { /* (ignored) */ /***/ }, /***/ 94304 /*!********************!*\ !*** fs (ignored) ***! \********************/ () { /* (ignored) */ /***/ }, /***/ 56559 /*!**********************!*\ !*** zlib (ignored) ***! \**********************/ () { /* (ignored) */ /***/ }, /***/ 41234 /*!************************!*\ !*** crypto (ignored) ***! \************************/ () { /* (ignored) */ /***/ }, /***/ 25189 /*!********************************************************!*\ !*** ./libs/dicom-image-loader-dev/constants/index.js ***! \********************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ transferSyntaxes: () => (/* reexport safe */ _transferSyntaxes__WEBPACK_IMPORTED_MODULE_0__["default"]) /* harmony export */ }); /* harmony import */ var _transferSyntaxes__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./transferSyntaxes */ 47901); /***/ }, /***/ 47901 /*!*******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/constants/transferSyntaxes.js ***! \*******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); const transferSyntaxes = { IMPLICIT_VR_LITTLE_ENDIAN: '1.2.840.10008.1.2', EXPLICIT_VR_LITTLE_ENDIAN: '1.2.840.10008.1.2.1', DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN: '1.2.840.10008.1.2.1.99', EXPLICIT_VR_BIG_ENDIAN: '1.2.840.10008.1.2.2', JPEG_BASELINE_PROCESS_1: '1.2.840.10008.1.2.4.50', JPEG_EXTENDED_PROCESS_2_4: '1.2.840.10008.1.2.4.51', JPEG_EXTENDED_PROCESSES_3_5: '1.2.840.10008.1.2.4.52', JPEG_SPECTRAL_SELECTION_NONHIERARCHICAL_PROCESSES_6_8: '1.2.840.10008.1.2.4.53', JPEG_SPECTRAL_SELECTION_NONHIERARCHICAL_PROCESSES_7_9: '1.2.840.10008.1.2.4.54', JPEG_FULL_PROGRESSION_NONHIERARCHICAL_PROCESSES_10_12: '1.2.840.10008.1.2.4.55', JPEG_FULL_PROGRESSION_NONHIERARCHICAL_PROCESSES_11_13: '1.2.840.10008.1.2.4.56', JPEG_LOSSLESS_NONHIERARCHICAL_PROCESS_14: '1.2.840.10008.1.2.4.57', JPEG_LOSSLESS_NONHIERARCHICAL_PROCESS_15: '1.2.840.10008.1.2.4.58', JPEG_EXTENDED_HIERARCHICAL_PROCESSES_16_18: '1.2.840.10008.1.2.4.59', JPEG_EXTENDED_HIERARCHICAL_PROCESSES_17_19: '1.2.840.10008.1.2.4.60', JPEG_SPECTRAL_SELECTION_HIERARCHICAL_PROCESSES_20_22: '1.2.840.10008.1.2.4.61', JPEG_SPECTRAL_SELECTION_HIERARCHICAL_PROCESSES_21_23: '1.2.840.10008.1.2.4.62', JPEG_FULL_PROGRESSION_HIERARCHICAL_PROCESSES_24_26: '1.2.840.10008.1.2.4.63', JPEG_FULL_PROGRESSION_HIERARCHICAL_PROCESSES_25_27: '1.2.840.10008.1.2.4.64', JPEG_LOSSLESS_NONHIERARCHICAL_PROCESS_28: '1.2.840.10008.1.2.4.65', JPEG_LOSSLESS_NONHIERARCHICAL_PROCESS_29: '1.2.840.10008.1.2.4.66', JPEG_LOSSLESS_NONHIERARCHICAL_FIRST_ORDER_PREDICTION_PROCESS_14: '1.2.840.10008.1.2.4.70', JPEG_LS_LOSSLESS_IMAGE_COMPRESSION: '1.2.840.10008.1.2.4.80', JPEG_LS_LOSSY_NEAR_LOSSLESS_IMAGE_COMPRESSION: '1.2.840.10008.1.2.4.81', JPEG_2000_IMAGE_COMPRESSION_LOSSLESS_ONLY: '1.2.840.10008.1.2.4.90', JPEG_2000_IMAGE_COMPRESSION: '1.2.840.10008.1.2.4.91', JPEG_2000_PART_2_MULTICOMPONENT_IMAGE_COMPRESSION_LOSSLESS_ONLY: '1.2.840.10008.1.2.4.92', JPEG_2000_PART_2_MULTICOMPONENT_IMAGE_COMPRESSION: '1.2.840.10008.1.2.4.93', JPIP_REFERENCED: '1.2.840.10008.1.2.4.94', JPIP_REFERENCED_DEFLATE: '1.2.840.10008.1.2.4.95', MPEG2_MAIN_PROFILE_MAIN_LEVEL: '1.2.840.10008.1.2.4.100', MPEG4_AVC_H264_HIGH_PROFILE_LEVEL_4_1: '1.2.840.10008.1.2.4.101', MPEG4_AVC_H264_BD_COMPATIBLE_HIGH_PROFILE_LEVEL_4_1: '1.2.840.10008.1.2.4.102', MPEG4_AVC_H264_HIGH_PROFILE_FOR_2D_VIDEO: '1.2.840.10008.1.2.4.103', MPEG4_AVC_H264_HIGH_PROFILE_FOR_3D_VIDEO: '1.2.840.10008.1.2.4.104', JPIP_LOSSLESS: '1.2.840.10008.1.2.4.96', JPIP_PART2_MULTICOMPONENT_IMAGE_COMPRESSION: '1.2.840.10008.1.2.4.97', RFC_2557_MIME_ENCAPSULATION: '1.2.840.10008.1.2.6.1', JPEG_XR_IMAGE_COMPRESSION: '1.2.840.10008.1.2.6.2', JPEG_2000_IMAGE_COMPRESSION_LOSSLESS_ONLY_RETIRED: '1.2.840.10008.1.2.4.90R', JPEG_2000_IMAGE_COMPRESSION_RETIRED: '1.2.840.10008.1.2.4.91R', JPEG_2000_PART_2_MULTICOMPONENT_IMAGE_COMPRESSION_LOSSLESS_ONLY_RETIRED: '1.2.840.10008.1.2.4.92R', JPEG_2000_PART_2_MULTICOMPONENT_IMAGE_COMPRESSION_RETIRED: '1.2.840.10008.1.2.4.93R' }; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (transferSyntaxes); /***/ }, /***/ 68149 /*!***************************************************************!*\ !*** ./libs/dicom-image-loader-dev/decodeImageFrameWorker.js ***! \***************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ decodeImageFrame: () => (/* binding */ decodeImageFrame) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! comlink */ 67159); /* harmony import */ var _shared_decoders_decodeBigEndian__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shared/decoders/decodeBigEndian */ 14148); /* harmony import */ var _shared_decoders_decodeHTJ2K__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shared/decoders/decodeHTJ2K */ 61368); /* harmony import */ var _shared_decoders_decodeJPEG2000__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./shared/decoders/decodeJPEG2000 */ 47061); /* harmony import */ var _shared_decoders_decodeJPEGBaseline8Bit__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./shared/decoders/decodeJPEGBaseline8Bit */ 94351); /* harmony import */ var _shared_decoders_decodeJPEGBaseline12Bit_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./shared/decoders/decodeJPEGBaseline12Bit-js */ 38314); /* harmony import */ var _shared_decoders_decodeJPEGLossless__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./shared/decoders/decodeJPEGLossless */ 92677); /* harmony import */ var _shared_decoders_decodeJPEGLS__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./shared/decoders/decodeJPEGLS */ 54782); /* harmony import */ var _shared_decoders_decodeLittleEndian__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./shared/decoders/decodeLittleEndian */ 31618); /* harmony import */ var _shared_decoders_decodeRLE__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./shared/decoders/decodeRLE */ 60144); /* harmony import */ var _shared_getMinMax__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./shared/getMinMax */ 67151); /* harmony import */ var _shared_getPixelDataTypeFromMinMax__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./shared/getPixelDataTypeFromMinMax */ 52783); /* harmony import */ var _shared_isColorImage__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./shared/isColorImage */ 93109); /* harmony import */ var _shared_scaling_bilinear__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./shared/scaling/bilinear */ 53076); /* harmony import */ var _shared_scaling_replicate__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./shared/scaling/replicate */ 2964); /* harmony import */ var _shared_scaling_scaleArray__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./shared/scaling/scaleArray */ 91344); const imageUtilities = { bilinear: _shared_scaling_bilinear__WEBPACK_IMPORTED_MODULE_14__["default"], replicate: _shared_scaling_replicate__WEBPACK_IMPORTED_MODULE_15__["default"] }; const typedArrayConstructors = { Uint8Array, Uint16Array, Int16Array, Float32Array }; function postProcessDecodedPixels(imageFrame, options, start, decodeConfig) { const shouldShift = imageFrame.pixelRepresentation !== undefined && imageFrame.pixelRepresentation === 1; const shift = shouldShift && imageFrame.bitsStored !== undefined ? 32 - imageFrame.bitsStored : undefined; if (shouldShift && shift !== undefined) { for (let index = 0; index < imageFrame.pixelData.length; index++) { imageFrame.pixelData[index] = imageFrame.pixelData[index] << shift >> shift; } } let pixelDataArray = imageFrame.pixelData; imageFrame.pixelDataLength = imageFrame.pixelData.length; const { min: minBeforeScale, max: maxBeforeScale } = (0,_shared_getMinMax__WEBPACK_IMPORTED_MODULE_11__["default"])(imageFrame.pixelData); const canRenderFloat = options.allowFloatRendering === undefined ? true : options.allowFloatRendering; let invalidType = (0,_shared_isColorImage__WEBPACK_IMPORTED_MODULE_13__["default"])(imageFrame.photometricInterpretation) && options.targetBuffer?.offset === undefined; const willScale = options.preScale?.enabled; const hasFloatRescale = willScale && Object.values(options.preScale.scalingParameters).some(v => typeof v === 'number' && !Number.isInteger(v)); const disableScale = !options.preScale.enabled || !canRenderFloat && hasFloatRescale; const type = options.targetBuffer?.type; if (type && options.preScale.enabled && !disableScale) { const { rescaleSlope, rescaleIntercept } = options.preScale.scalingParameters; const minAfterScale = rescaleSlope * minBeforeScale + rescaleIntercept; const maxAfterScale = rescaleSlope * maxBeforeScale + rescaleIntercept; invalidType = !(0,_shared_getPixelDataTypeFromMinMax__WEBPACK_IMPORTED_MODULE_12__.validatePixelDataType)(minAfterScale, maxAfterScale, typedArrayConstructors[type]); } if (type && !invalidType) { pixelDataArray = _handleTargetBuffer(options, imageFrame, typedArrayConstructors, pixelDataArray); } else if (options.preScale.enabled && !disableScale) { pixelDataArray = _handlePreScaleSetup(options, minBeforeScale, maxBeforeScale, imageFrame); } else { pixelDataArray = _getDefaultPixelDataArray(minBeforeScale, maxBeforeScale, imageFrame); } let minAfterScale = minBeforeScale; let maxAfterScale = maxBeforeScale; if (options.preScale.enabled && !disableScale) { const scalingParameters = options.preScale.scalingParameters; _validateScalingParameters(scalingParameters); const { rescaleSlope, rescaleIntercept } = scalingParameters; const isSlopeAndInterceptNumbers = typeof rescaleSlope === 'number' && typeof rescaleIntercept === 'number'; if (isSlopeAndInterceptNumbers) { (0,_shared_scaling_scaleArray__WEBPACK_IMPORTED_MODULE_16__["default"])(pixelDataArray, scalingParameters); imageFrame.preScale = { ...options.preScale, scaled: true }; const { rescaleIntercept, rescaleSlope, suvbw } = scalingParameters; minAfterScale = rescaleSlope * minBeforeScale + rescaleIntercept; maxAfterScale = rescaleSlope * maxBeforeScale + rescaleIntercept; if (suvbw) { minAfterScale = minAfterScale * suvbw; maxAfterScale = maxAfterScale * suvbw; } } } else if (disableScale) { imageFrame.preScale = { enabled: true, scaled: false }; minAfterScale = minBeforeScale; maxAfterScale = maxBeforeScale; } imageFrame.pixelData = pixelDataArray; imageFrame.smallestPixelValue = minAfterScale; imageFrame.largestPixelValue = maxAfterScale; const end = Date.now(); imageFrame.decodeTimeInMS = end - start; return imageFrame; } function _handleTargetBuffer(options, imageFrame, typedArrayConstructors, pixelDataArray) { const { arrayBuffer, type, offset: rawOffset = 0, length: rawLength, rows } = options.targetBuffer; const TypedArrayConstructor = typedArrayConstructors[type]; if (!TypedArrayConstructor) { throw new Error(`target array ${type} is not supported, or doesn't exist.`); } if (rows && rows != imageFrame.rows) { scaleImageFrame(imageFrame, options.targetBuffer, TypedArrayConstructor); } const imageFrameLength = imageFrame.pixelDataLength; const offset = rawOffset; const length = rawLength !== null && rawLength !== undefined ? rawLength : imageFrameLength - offset; const imageFramePixelData = imageFrame.pixelData; if (length !== imageFramePixelData.length) { throw new Error(`target array for image does not have the same length (${length}) as the decoded image length (${imageFramePixelData.length}).`); } const typedArray = arrayBuffer ? new TypedArrayConstructor(arrayBuffer, offset, length) : new TypedArrayConstructor(length); typedArray.set(imageFramePixelData, 0); pixelDataArray = typedArray; return pixelDataArray; } function _handlePreScaleSetup(options, minBeforeScale, maxBeforeScale, imageFrame) { const scalingParameters = options.preScale.scalingParameters; _validateScalingParameters(scalingParameters); const { rescaleSlope, rescaleIntercept } = scalingParameters; const areSlopeAndInterceptNumbers = typeof rescaleSlope === 'number' && typeof rescaleIntercept === 'number'; let scaledMin = minBeforeScale; let scaledMax = maxBeforeScale; if (areSlopeAndInterceptNumbers) { scaledMin = rescaleSlope * minBeforeScale + rescaleIntercept; scaledMax = rescaleSlope * maxBeforeScale + rescaleIntercept; } return _getDefaultPixelDataArray(scaledMin, scaledMax, imageFrame); } function _getDefaultPixelDataArray(min, max, imageFrame) { const TypedArrayConstructor = (0,_shared_getPixelDataTypeFromMinMax__WEBPACK_IMPORTED_MODULE_12__["default"])(min, max); const typedArray = new TypedArrayConstructor(imageFrame.pixelData.length); typedArray.set(imageFrame.pixelData, 0); return typedArray; } function _validateScalingParameters(scalingParameters) { if (!scalingParameters) { throw new Error('options.preScale.scalingParameters must be defined if preScale.enabled is true, and scalingParameters cannot be derived from the metadata providers.'); } } function createDestinationImage(imageFrame, targetBuffer, TypedArrayConstructor) { const { samplesPerPixel } = imageFrame; const { rows, columns } = targetBuffer; const typedLength = rows * columns * samplesPerPixel; const pixelData = new TypedArrayConstructor(typedLength); const bytesPerPixel = pixelData.byteLength / typedLength; return { pixelData, rows, columns, frameInfo: { ...imageFrame.frameInfo, rows, columns }, imageInfo: { ...imageFrame.imageInfo, rows, columns, bytesPerPixel } }; } function scaleImageFrame(imageFrame, targetBuffer, TypedArrayConstructor) { const destination = createDestinationImage(imageFrame, targetBuffer, TypedArrayConstructor); const { scalingType = 'replicate' } = targetBuffer; imageUtilities[scalingType](imageFrame, destination); Object.assign(imageFrame, destination); imageFrame.pixelDataLength = imageFrame.pixelData.length; return imageFrame; } function decodeImageFrame(_x, _x2, _x3, _x4, _x5, _x6) { return _decodeImageFrame.apply(this, arguments); } function _decodeImageFrame() { _decodeImageFrame = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, transferSyntax, pixelData, decodeConfig, options, callbackFunction) { const start = Date.now(); let decodePromise = null; let options_; switch (transferSyntax) { case '1.2.840.10008.1.2': case '1.2.840.10008.1.2.1': { decodePromise = (0,_shared_decoders_decodeLittleEndian__WEBPACK_IMPORTED_MODULE_9__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.1.99': { decodePromise = (0,_shared_decoders_decodeLittleEndian__WEBPACK_IMPORTED_MODULE_9__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.2': { decodePromise = (0,_shared_decoders_decodeBigEndian__WEBPACK_IMPORTED_MODULE_2__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.4.201': case '1.2.840.10008.1.2.4.202': case '1.2.840.10008.1.2.4.203': case '3.2.840.10008.1.2.4.96': { options_ = { ...imageFrame }; decodePromise = (0,_shared_decoders_decodeHTJ2K__WEBPACK_IMPORTED_MODULE_3__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecOpenJph); break; } case '1.2.840.10008.1.2.4.50': { options_ = { ...imageFrame }; decodePromise = (0,_shared_decoders_decodeJPEGBaseline8Bit__WEBPACK_IMPORTED_MODULE_5__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecLibJpegTurbo8bit); break; } case '1.2.840.10008.1.2.4.51': { decodePromise = (0,_shared_decoders_decodeJPEGBaseline12Bit_js__WEBPACK_IMPORTED_MODULE_6__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.4.57': { decodePromise = (0,_shared_decoders_decodeJPEGLossless__WEBPACK_IMPORTED_MODULE_7__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.4.70': { decodePromise = (0,_shared_decoders_decodeJPEGLossless__WEBPACK_IMPORTED_MODULE_7__["default"])(imageFrame, pixelData); break; } case '1.2.840.10008.1.2.4.80': { options_ = { signed: imageFrame.pixelRepresentation === 1, bytesPerPixel: imageFrame.bitsAllocated <= 8 ? 1 : 2, ...imageFrame }; decodePromise = (0,_shared_decoders_decodeJPEGLS__WEBPACK_IMPORTED_MODULE_8__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecCharls); break; } case '1.2.840.10008.1.2.4.81': { options_ = { signed: imageFrame.pixelRepresentation === 1, bytesPerPixel: imageFrame.bitsAllocated <= 8 ? 1 : 2, ...imageFrame }; decodePromise = (0,_shared_decoders_decodeJPEGLS__WEBPACK_IMPORTED_MODULE_8__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecCharls); break; } case '1.2.840.10008.1.2.4.90': { options_ = { ...imageFrame }; decodePromise = (0,_shared_decoders_decodeJPEG2000__WEBPACK_IMPORTED_MODULE_4__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecOpenJpeg); break; } case '1.2.840.10008.1.2.4.91': { options_ = { ...imageFrame }; decodePromise = (0,_shared_decoders_decodeJPEG2000__WEBPACK_IMPORTED_MODULE_4__["default"])(pixelData, options_, decodeConfig?.wasmUrlCodecOpenJpeg); break; } case '1.2.840.10008.1.2.5': { decodePromise = (0,_shared_decoders_decodeRLE__WEBPACK_IMPORTED_MODULE_10__["default"])(imageFrame, pixelData); break; } default: { throw new Error(`no decoder for transfer syntax ${transferSyntax}`); } } if (!decodePromise) { throw new Error('decodePromise not defined'); } const decodedFrame = yield decodePromise; const postProcessed = postProcessDecodedPixels(decodedFrame, options, start, decodeConfig); callbackFunction?.(postProcessed); return postProcessed; }); return _decodeImageFrame.apply(this, arguments); } const object = { decodeTask({ imageFrame, transferSyntax, decodeConfig, options, pixelData, callbackFn }) { return decodeImageFrame(imageFrame, transferSyntax, pixelData, decodeConfig, options, callbackFn); } }; (0,comlink__WEBPACK_IMPORTED_MODULE_1__.expose)(object); /***/ }, /***/ 95924 /*!*********************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertPALETTECOLOR.js ***! \*********************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); function convertLUTto8Bit(lut, shift) { const numberEntries = lut.length; const cleanedLUT = new Uint8ClampedArray(numberEntries); for (let index = 0; index < numberEntries; ++index) { cleanedLUT[index] = lut[index] >> shift; } return cleanedLUT; } function fetchPaletteData(imageFrame, color, fallback) { const data = imageFrame[`${color}PaletteColorLookupTableData`]; if (data) { return Promise.resolve(data); } const result = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__.get('imagePixelModule', imageFrame.imageId); return result && typeof result.then === 'function' ? result.then(module => module ? module[`${color}PaletteColorLookupTableData`] : fallback) : Promise.resolve(result ? result[`${color}PaletteColorLookupTableData`] : fallback); } /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { const numberPixels = imageFrame.columns * imageFrame.rows; const pixelData = imageFrame.pixelData; Promise.all([fetchPaletteData(imageFrame, 'red', null), fetchPaletteData(imageFrame, 'green', null), fetchPaletteData(imageFrame, 'blue', null)]).then(([rData, gData, bData]) => { if (!rData || !gData || !bData) { throw new Error('The image does not have a complete color palette. R, G, and B palette data are required.'); } const length_ = rData.length; let palIndex = 0; let bufferIndex = 0; const start = imageFrame.redPaletteColorLookupTableDescriptor[1]; const shift = imageFrame.redPaletteColorLookupTableDescriptor[2] === 8 ? 0 : 8; const rDataCleaned = convertLUTto8Bit(rData, shift); const gDataCleaned = convertLUTto8Bit(gData, shift); const bDataCleaned = convertLUTto8Bit(bData, shift); if (useRGBA) { for (let index = 0; index < numberPixels; ++index) { let value = pixelData[palIndex++]; if (value < start) { value = 0; } else if (value > start + length_ - 1) { value = length_ - 1; } else { value -= start; } colorBuffer[bufferIndex++] = rDataCleaned[value]; colorBuffer[bufferIndex++] = gDataCleaned[value]; colorBuffer[bufferIndex++] = bDataCleaned[value]; colorBuffer[bufferIndex++] = 255; } return; } for (let index = 0; index < numberPixels; ++index) { let value = pixelData[palIndex++]; if (value < start) { value = 0; } else if (value > start + length_ - 1) { value = length_ - 1; } else { value -= start; } colorBuffer[bufferIndex++] = rDataCleaned[value]; colorBuffer[bufferIndex++] = gDataCleaned[value]; colorBuffer[bufferIndex++] = bDataCleaned[value]; } }); } /***/ }, /***/ 4245 /*!************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertRGBColorByPixel.js ***! \************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { if (imageFrame === undefined) { throw new Error('decodeRGB: rgbBuffer must be defined'); } if (imageFrame.length % 3 !== 0) { throw new Error(`decodeRGB: rgbBuffer length ${imageFrame.length} must be divisible by 3`); } const numberPixels = imageFrame.length / 3; let rgbIndex = 0; let bufferIndex = 0; if (useRGBA) { for (let index = 0; index < numberPixels; index++) { colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; colorBuffer[bufferIndex++] = 255; } return; } colorBuffer.set(imageFrame); } /***/ }, /***/ 56495 /*!************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertRGBColorByPlane.js ***! \************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { if (imageFrame === undefined) { throw new Error('decodeRGB: rgbBuffer must be defined'); } if (imageFrame.length % 3 !== 0) { throw new Error(`decodeRGB: rgbBuffer length ${imageFrame.length} must be divisible by 3`); } const numberPixels = imageFrame.length / 3; let bufferIndex = 0; let rIndex = 0; let gIndex = numberPixels; let bIndex = numberPixels * 2; if (useRGBA) { for (let index = 0; index < numberPixels; index++) { colorBuffer[bufferIndex++] = imageFrame[rIndex++]; colorBuffer[bufferIndex++] = imageFrame[gIndex++]; colorBuffer[bufferIndex++] = imageFrame[bIndex++]; colorBuffer[bufferIndex++] = 255; } } else { for (let index = 0; index < numberPixels; index++) { colorBuffer[bufferIndex++] = imageFrame[rIndex++]; colorBuffer[bufferIndex++] = imageFrame[gIndex++]; colorBuffer[bufferIndex++] = imageFrame[bIndex++]; } } } /***/ }, /***/ 33533 /*!**************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertYBRFull422ByPixel.js ***! \**************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { if (imageFrame === undefined) { throw new Error('convertYBRFull422ByPixel: ybrBuffer must be defined'); } if (imageFrame.length % 2 !== 0) { throw new Error(`convertYBRFull422ByPixel: ybrBuffer length ${imageFrame.length} must be divisible by 2`); } const numberPixels = imageFrame.length / 2; let ybrIndex = 0; let bufferIndex = 0; if (useRGBA) { for (let index = 0; index < numberPixels; index += 2) { const y1 = imageFrame[ybrIndex++]; const y2 = imageFrame[ybrIndex++]; const callback = imageFrame[ybrIndex++]; const cr = imageFrame[ybrIndex++]; colorBuffer[bufferIndex++] = y1 + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y1 - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y1 + 1.772 * (callback - 128); colorBuffer[bufferIndex++] = 255; colorBuffer[bufferIndex++] = y2 + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y2 - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y2 + 1.772 * (callback - 128); colorBuffer[bufferIndex++] = 255; } return; } for (let index = 0; index < numberPixels; index += 2) { const y1 = imageFrame[ybrIndex++]; const y2 = imageFrame[ybrIndex++]; const callback = imageFrame[ybrIndex++]; const cr = imageFrame[ybrIndex++]; colorBuffer[bufferIndex++] = y1 + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y1 - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y1 + 1.772 * (callback - 128); colorBuffer[bufferIndex++] = y2 + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y2 - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y2 + 1.772 * (callback - 128); } } /***/ }, /***/ 10427 /*!***********************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertYBRFullByPixel.js ***! \***********************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { if (imageFrame === undefined) { throw new Error('convertYBRFullByPixel: ybrBuffer must be defined'); } if (imageFrame.length % 3 !== 0) { throw new Error(`convertYBRFullByPixel: ybrBuffer length ${imageFrame.length} must be divisible by 3`); } const numberPixels = imageFrame.length / 3; let ybrIndex = 0; let bufferIndex = 0; if (useRGBA) { for (let index = 0; index < numberPixels; index++) { const y = imageFrame[ybrIndex++]; const callback = imageFrame[ybrIndex++]; const cr = imageFrame[ybrIndex++]; colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y + 1.772 * (callback - 128); colorBuffer[bufferIndex++] = 255; } return; } for (let index = 0; index < numberPixels; index++) { const y = imageFrame[ybrIndex++]; const callback = imageFrame[ybrIndex++]; const cr = imageFrame[ybrIndex++]; colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y + 1.772 * (callback - 128); } } /***/ }, /***/ 8121 /*!***********************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/convertYBRFullByPlane.js ***! \***********************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(imageFrame, colorBuffer, useRGBA) { if (imageFrame === undefined) { throw new Error('convertYBRFullByPlane: ybrBuffer must be defined'); } if (imageFrame.length % 3 !== 0) { throw new Error(`convertYBRFullByPlane: ybrBuffer length ${imageFrame.length} must be divisible by 3`); } const numberPixels = imageFrame.length / 3; let bufferIndex = 0; let yIndex = 0; let callbackIndex = numberPixels; let crIndex = numberPixels * 2; if (useRGBA) { for (let index = 0; index < numberPixels; index++) { const y = imageFrame[yIndex++]; const callback = imageFrame[callbackIndex++]; const cr = imageFrame[crIndex++]; colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y + 1.772 * (callback - 128); colorBuffer[bufferIndex++] = 255; } return; } for (let index = 0; index < numberPixels; index++) { const y = imageFrame[yIndex++]; const callback = imageFrame[callbackIndex++]; const cr = imageFrame[crIndex++]; colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); colorBuffer[bufferIndex++] = y - 0.344_14 * (callback - 128) - 0.714_14 * (cr - 128); colorBuffer[bufferIndex++] = y + 1.772 * (callback - 128); } } /***/ }, /***/ 62109 /*!*******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/colorSpaceConverters/index.js ***! \*******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ convertPALETTECOLOR: () => (/* reexport safe */ _convertPALETTECOLOR__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ convertRGBColorByPixel: () => (/* reexport safe */ _convertRGBColorByPixel__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ convertRGBColorByPlane: () => (/* reexport safe */ _convertRGBColorByPlane__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ convertYBRFull422ByPixel: () => (/* reexport safe */ _convertYBRFull422ByPixel__WEBPACK_IMPORTED_MODULE_3__["default"]), /* harmony export */ convertYBRFullByPixel: () => (/* reexport safe */ _convertYBRFullByPixel__WEBPACK_IMPORTED_MODULE_4__["default"]), /* harmony export */ convertYBRFullByPlane: () => (/* reexport safe */ _convertYBRFullByPlane__WEBPACK_IMPORTED_MODULE_5__["default"]) /* harmony export */ }); /* harmony import */ var _convertPALETTECOLOR__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./convertPALETTECOLOR */ 95924); /* harmony import */ var _convertRGBColorByPixel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./convertRGBColorByPixel */ 4245); /* harmony import */ var _convertRGBColorByPlane__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./convertRGBColorByPlane */ 56495); /* harmony import */ var _convertYBRFull422ByPixel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./convertYBRFull422ByPixel */ 33533); /* harmony import */ var _convertYBRFullByPixel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./convertYBRFullByPixel */ 10427); /* harmony import */ var _convertYBRFullByPlane__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./convertYBRFullByPlane */ 8121); /***/ }, /***/ 28110 /*!**********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/convertColorSpace.js ***! \**********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ convertColorSpace) /* harmony export */ }); /* harmony import */ var _colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./colorSpaceConverters/index */ 62109); function convertRGB(imageFrame, colorBuffer, useRGBA) { if (imageFrame.planarConfiguration === 0) { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertRGBColorByPixel)(imageFrame.pixelData, colorBuffer, useRGBA); } else { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertRGBColorByPlane)(imageFrame.pixelData, colorBuffer, useRGBA); } } function convertYBRFull(imageFrame, colorBuffer, useRGBA) { if (imageFrame.planarConfiguration === 0) { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertYBRFullByPixel)(imageFrame.pixelData, colorBuffer, useRGBA); } else { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertYBRFullByPlane)(imageFrame.pixelData, colorBuffer, useRGBA); } } function convertColorSpace(imageFrame, colorBuffer, useRGBA) { switch (imageFrame.photometricInterpretation) { case 'PALETTE COLOR': { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertPALETTECOLOR)(imageFrame, colorBuffer, useRGBA); break; } case 'RGB': { convertRGB(imageFrame, colorBuffer, useRGBA); break; } case 'YBR_FULL': { convertYBRFull(imageFrame, colorBuffer, useRGBA); break; } case 'YBR_FULL_422': { (0,_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_0__.convertYBRFull422ByPixel)(imageFrame.pixelData, colorBuffer, useRGBA); break; } case 'YBR_ICT': { convertRGB(imageFrame, colorBuffer, useRGBA); break; } case 'YBR_RCT': { convertRGB(imageFrame, colorBuffer, useRGBA); break; } default: { throw new Error(`No color space conversion for photometric interpretation ${imageFrame.photometricInterpretation}`); } } } /***/ }, /***/ 22555 /*!****************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/createImage.js ***! \****************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 15678); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 14430); /* harmony import */ var _shared_getMinMax__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../shared/getMinMax */ 67151); /* harmony import */ var _shared_isColorImage__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../shared/isColorImage */ 93109); /* harmony import */ var _convertColorSpace__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./convertColorSpace */ 28110); /* harmony import */ var _decodeImageFrame__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./decodeImageFrame */ 60772); /* harmony import */ var _getImageFrame__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./getImageFrame */ 56076); /* harmony import */ var _getScalingParameters__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./getScalingParameters */ 65102); /* harmony import */ var _internal_options__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./internal/options */ 51500); /* harmony import */ var _isColorConversionRequired__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./isColorConversionRequired */ 75056); /* harmony import */ var _isModalityLutForDisplay__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./isModalityLutForDisplay */ 22561); /* harmony import */ var _removeAFromRGBA__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./removeAFromRGBA */ 7587); /* harmony import */ var _setPixelDataType__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./setPixelDataType */ 13956); let lastImageIdDrawn = ''; function createImage(imageId, pixelData, transferSyntax, options = {}) { const useRGBA = options.useRGBA; options.preScale = { enabled: options.preScale && options.preScale.enabled !== undefined ? options.preScale.enabled : true }; if (!pixelData?.length) { return Promise.reject(new Error('The pixel data is missing')); } const { MetadataModules } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; const canvas = document.createElement('canvas'); const imageFrame = (0,_getImageFrame__WEBPACK_IMPORTED_MODULE_8__["default"])(imageId); imageFrame.decodeLevel = options.decodeLevel; options.allowFloatRendering = (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__.canRenderFloatTextures)(); if (options.preScale.enabled) { const scalingParameters = (0,_getScalingParameters__WEBPACK_IMPORTED_MODULE_9__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__, imageId); if (scalingParameters) { options.preScale = { ...options.preScale, scalingParameters: scalingParameters }; } } const { decodeConfig } = (0,_internal_options__WEBPACK_IMPORTED_MODULE_10__.getOptions)(); for (const key of Object.keys(imageFrame)) { if (typeof imageFrame[key] === 'function' || imageFrame[key] instanceof Promise) { delete imageFrame[key]; } } const decodePromise = (0,_decodeImageFrame__WEBPACK_IMPORTED_MODULE_7__["default"])(imageFrame, transferSyntax, pixelData, canvas, options, decodeConfig); const isColorImage = (0,_shared_isColorImage__WEBPACK_IMPORTED_MODULE_5__["default"])(imageFrame.photometricInterpretation); return new Promise((resolve, reject) => { decodePromise.then(function (imageFrame) { let alreadyTyped = false; if (options.targetBuffer && options.targetBuffer.type && !isColorImage) { const { arrayBuffer, type, offset: rawOffset = 0, length: rawLength } = options.targetBuffer; const imageFrameLength = imageFrame.pixelDataLength; const offset = rawOffset; const length = rawLength !== null && rawLength !== undefined ? rawLength : imageFrameLength - offset; const typedArrayConstructors = { Uint8Array, Uint16Array, Int16Array, Float32Array }; if (length !== imageFrame.pixelDataLength) { throw new Error(`target array for image does not have the same length (${length}) as the decoded image length (${imageFrame.pixelDataLength}).`); } const TypedArrayConstructor = typedArrayConstructors[type]; const typedArray = arrayBuffer ? new TypedArrayConstructor(arrayBuffer, offset, length) : new TypedArrayConstructor(imageFrame.pixelData); if (length !== imageFrame.pixelDataLength) { throw new Error('target array for image does not have the same length as the decoded image length.'); } imageFrame.pixelData = typedArray; alreadyTyped = true; } if (!alreadyTyped) { (0,_setPixelDataType__WEBPACK_IMPORTED_MODULE_14__["default"])(imageFrame); } const imagePlaneModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.get(MetadataModules.IMAGE_PLANE, imageId) || {}; const voiLutModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.get(MetadataModules.VOI_LUT, imageId) || {}; const modalityLutModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.get(MetadataModules.MODALITY_LUT, imageId) || {}; const sopCommonModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.get(MetadataModules.SOP_COMMON, imageId) || {}; const calibrationModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.get(MetadataModules.CALIBRATION, imageId) || {}; const { rows, columns } = imageFrame; if (isColorImage) { if ((0,_isColorConversionRequired__WEBPACK_IMPORTED_MODULE_11__["default"])(imageFrame)) { canvas.height = imageFrame.rows; canvas.width = imageFrame.columns; const context = canvas.getContext('2d'); let imageData = context.createImageData(imageFrame.columns, imageFrame.rows); if (!useRGBA) { imageData = { ...imageData, data: new Uint8ClampedArray(3 * imageFrame.columns * imageFrame.rows) }; } (0,_convertColorSpace__WEBPACK_IMPORTED_MODULE_6__["default"])(imageFrame, imageData.data, useRGBA); imageFrame.imageData = imageData; imageFrame.pixelData = imageData.data; imageFrame.pixelDataLength = imageData.data.length; } else if (!useRGBA && imageFrame.pixelDataLength === 4 * rows * columns) { const colorBuffer = new Uint8Array(imageFrame.pixelData.length / 4 * 3); imageFrame.pixelData = (0,_removeAFromRGBA__WEBPACK_IMPORTED_MODULE_13__["default"])(imageFrame.pixelData, colorBuffer); imageFrame.pixelDataLength = imageFrame.pixelData.length; } const minMax = (0,_shared_getMinMax__WEBPACK_IMPORTED_MODULE_4__["default"])(imageFrame.pixelData); imageFrame.smallestPixelValue = minMax.min; imageFrame.largestPixelValue = minMax.max; } const voxelManager = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"].createImageVoxelManager({ scalarData: imageFrame.pixelData, width: imageFrame.columns, height: imageFrame.rows, numberOfComponents: imageFrame.samplesPerPixel }); const image = { imageId, dataType: imageFrame.pixelData.constructor.name, color: isColorImage, calibration: calibrationModule, columnPixelSpacing: imagePlaneModule.columnPixelSpacing, columns: imageFrame.columns, height: imageFrame.rows, preScale: imageFrame.preScale, intercept: modalityLutModule.rescaleIntercept ? modalityLutModule.rescaleIntercept : 0, slope: modalityLutModule.rescaleSlope ? modalityLutModule.rescaleSlope : 1, invert: imageFrame.photometricInterpretation === 'MONOCHROME1', minPixelValue: imageFrame.smallestPixelValue, maxPixelValue: imageFrame.largestPixelValue, rowPixelSpacing: imagePlaneModule.rowPixelSpacing, rows: imageFrame.rows, sizeInBytes: imageFrame.pixelData.byteLength, width: imageFrame.columns, windowCenter: voiLutModule.windowCenter ? voiLutModule.windowCenter[0] : undefined, windowWidth: voiLutModule.windowWidth ? voiLutModule.windowWidth[0] : undefined, voiLUTFunction: voiLutModule.voiLUTFunction ? voiLutModule.voiLUTFunction : undefined, decodeTimeInMS: imageFrame.decodeTimeInMS, floatPixelData: undefined, imageFrame, voxelManager, rgba: isColorImage && useRGBA, getPixelData: () => imageFrame.pixelData, getCanvas: undefined, numberOfComponents: imageFrame.samplesPerPixel }; if (image.color) { image.getCanvas = function () { if (lastImageIdDrawn === imageId) { return canvas; } const width = image.columns; const height = image.rows; canvas.height = height; canvas.width = width; const context = canvas.getContext('2d'); const imageData = context.createImageData(width, height); const array = imageFrame.pixelData; if (array.length === width * height * 4) { for (const [index, element] of array.entries()) { imageData.data[index] = element; } } else if (array.length === width * height * 3) { let index = 0; for (let index_ = 0; index_ < array.length; index_ += 3) { imageData.data[index++] = array[index_]; imageData.data[index++] = array[index_ + 1]; imageData.data[index++] = array[index_ + 2]; imageData.data[index++] = 255; } } imageFrame.pixelData = imageData.data; imageFrame.pixelDataLength = imageData.data.length; imageFrame.imageData = imageData; context.putImageData(imageFrame.imageData, 0, 0); lastImageIdDrawn = imageId; return canvas; }; } if (modalityLutModule.modalityLUTSequence && modalityLutModule.modalityLUTSequence.length > 0 && (0,_isModalityLutForDisplay__WEBPACK_IMPORTED_MODULE_12__["default"])(sopCommonModule.sopClassUID)) { image.modalityLUT = modalityLutModule.modalityLUTSequence[0]; } if (voiLutModule.voiLUTSequence && voiLutModule.voiLUTSequence.length > 0) { image.voiLUT = voiLutModule.voiLUTSequence[0]; } if (image.color) { image.windowWidth = 256; image.windowCenter = 128; } if (image.windowCenter === undefined || image.windowWidth === undefined) { const minVoi = image.imageFrame.smallestPixelValue; const maxVoi = image.imageFrame.largestPixelValue; image.windowWidth = maxVoi - minVoi; image.windowCenter = (maxVoi + minVoi) / 2; } resolve(image); }, reject); }); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (createImage); /***/ }, /***/ 60772 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/decodeImageFrame.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 15678); /* harmony import */ var _decodeJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./decodeJPEGBaseline8BitColor */ 78669); function processDecodeTask(imageFrame, transferSyntax, pixelData, sourceOptions, decodeConfig) { const options = { ...sourceOptions }; delete options.loader; delete options.streamingData; const webWorkerManager = (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__.getWebWorkerManager)(); const priority = options.priority || undefined; const transferList = options.transferPixelData ? [pixelData.buffer] : undefined; return webWorkerManager.executeTask('dicomImageLoader', 'decodeTask', { imageFrame, transferSyntax, pixelData, options, decodeConfig }, { priority, requestType: options?.requestType }); } function decodeImageFrame(imageFrame, transferSyntax, pixelData, canvas, options = {}, decodeConfig) { switch (transferSyntax) { case '1.2.840.10008.1.2': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.1': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.1.99': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.2': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.201': case '1.2.840.10008.1.2.4.202': case '1.2.840.10008.1.2.4.203': case '3.2.840.10008.1.2.4.96': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.50': { if (imageFrame.bitsAllocated === 8 && (imageFrame.samplesPerPixel === 3 || imageFrame.samplesPerPixel === 4)) { return (0,_decodeJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_1__["default"])(imageFrame, pixelData, canvas); } return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.51': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.57': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.70': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.80': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.81': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.90': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.4.91': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } case '1.2.840.10008.1.2.5': { return processDecodeTask(imageFrame, transferSyntax, pixelData, options, decodeConfig); } } return Promise.reject(new Error(`No decoder for transfer syntax ${transferSyntax}`)); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeImageFrame); /***/ }, /***/ 78669 /*!********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/decodeJPEGBaseline8BitColor.js ***! \********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _shared_getMinMax__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shared/getMinMax */ 67151); function arrayBufferToString(buffer) { return binaryToString(String.fromCharCode.apply(null, Array.prototype.slice.apply(new Uint8Array(buffer)))); } function binaryToString(binary) { let error; try { return decodeURIComponent(escape(binary)); } catch (_error) { error = _error; if (error instanceof URIError) { return binary; } throw error; } } function decodeJPEGBaseline8BitColor(imageFrame, pixelData, canvas) { const start = Date.now(); const imgBlob = new Blob([pixelData], { type: 'image/jpeg' }); return new Promise((resolve, reject) => { const fileReader = new FileReader(); if (fileReader.readAsBinaryString === undefined) { fileReader.readAsArrayBuffer(imgBlob); } else { fileReader.readAsBinaryString(imgBlob); } fileReader.addEventListener('load', function () { const img = new Image(); img.addEventListener('load', function () { canvas.height = img.height; canvas.width = img.width; imageFrame.rows = img.height; imageFrame.columns = img.width; const context = canvas.getContext('2d'); context.drawImage(this, 0, 0); const imageData = context.getImageData(0, 0, img.width, img.height); const end = Date.now(); imageFrame.pixelData = new Uint8Array(imageData.data.buffer); imageFrame.imageData = imageData; imageFrame.decodeTimeInMS = end - start; const minMax = (0,_shared_getMinMax__WEBPACK_IMPORTED_MODULE_0__["default"])(imageFrame.pixelData); imageFrame.smallestPixelValue = minMax.min; imageFrame.largestPixelValue = minMax.max; imageFrame.pixelDataLength = imageFrame.pixelData.length; resolve(imageFrame); }); img.onerror = function (error) { reject(error); }; img.src = fileReader.readAsBinaryString === undefined ? `data:image/jpeg;base64,${globalThis.btoa(arrayBufferToString(fileReader.result))}` : `data:image/jpeg;base64,${globalThis.btoa(fileReader.result)}`; }); fileReader.onerror = e => { reject(e); }; }); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeJPEGBaseline8BitColor); /***/ }, /***/ 56076 /*!******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/getImageFrame.js ***! \******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); function getImageFrame(imageId) { const imagePixelModule = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__.get('imagePixelModule', imageId); return { samplesPerPixel: imagePixelModule.samplesPerPixel, photometricInterpretation: imagePixelModule.photometricInterpretation, planarConfiguration: imagePixelModule.planarConfiguration, rows: imagePixelModule.rows, columns: imagePixelModule.columns, bitsAllocated: imagePixelModule.bitsAllocated, bitsStored: imagePixelModule.bitsStored, pixelRepresentation: imagePixelModule.pixelRepresentation, smallestPixelValue: imagePixelModule.smallestPixelValue, largestPixelValue: imagePixelModule.largestPixelValue, redPaletteColorLookupTableDescriptor: imagePixelModule.redPaletteColorLookupTableDescriptor, greenPaletteColorLookupTableDescriptor: imagePixelModule.greenPaletteColorLookupTableDescriptor, bluePaletteColorLookupTableDescriptor: imagePixelModule.bluePaletteColorLookupTableDescriptor, redPaletteColorLookupTableData: imagePixelModule.redPaletteColorLookupTableData, greenPaletteColorLookupTableData: imagePixelModule.greenPaletteColorLookupTableData, bluePaletteColorLookupTableData: imagePixelModule.bluePaletteColorLookupTableData, pixelData: undefined, imageId }; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getImageFrame); /***/ }, /***/ 20645 /*!**********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/getInstanceModule.js ***! \**********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getInstanceModule: () => (/* binding */ getInstanceModule), /* harmony export */ instanceModuleNames: () => (/* binding */ instanceModuleNames) /* harmony export */ }); function getInstanceModule(imageId, metaDataProvider, types) { const result = {}; for (const t of types) { try { const data = metaDataProvider(t, imageId); if (data) { const capitalizedData = {}; for (const key in data) { if (key in data) { const capitalizedKey = capitalizeTag(key); capitalizedData[capitalizedKey] = data[key]; } } Object.assign(result, capitalizedData); } } catch (error) { console.error(`Error retrieving ${t} data:`, error); } } return result; } const capitalizeTag = tag => tag.charAt(0).toUpperCase() + tag.slice(1); const instanceModuleNames = ['multiframeModule', 'generalSeriesModule', 'patientStudyModule', 'imagePlaneModule', 'nmMultiframeGeometryModule', 'imagePixelModule', 'modalityLutModule', 'voiLutModule', 'sopCommonModule', 'petIsotopeModule', 'overlayPlaneModule', 'transferSyntax', 'petSeriesModule', 'petImageModule']; /***/ }, /***/ 65102 /*!*************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/getScalingParameters.js ***! \*************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getScalingParameters) /* harmony export */ }); function getScalingParameters(metaData, imageId) { const modalityLutModule = metaData.get('modalityLutModule', imageId) || {}; const generalSeriesModule = metaData.get('generalSeriesModule', imageId) || {}; const { modality } = generalSeriesModule; const scalingParameters = { rescaleSlope: modalityLutModule.rescaleSlope, rescaleIntercept: modalityLutModule.rescaleIntercept, modality }; const suvFactor = metaData.get('scalingModule', imageId) || {}; return { ...scalingParameters, ...(modality === 'PT' && { suvbw: suvFactor.suvbw }) }; } /***/ }, /***/ 973 /*!*****************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/imageIdToURI.js ***! \*****************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ imageIdToURI) /* harmony export */ }); function imageIdToURI(imageId) { const colonIndex = imageId.indexOf(':'); return imageId.slice(Math.max(0, colonIndex + 1)); } /***/ }, /***/ 52610 /*!*******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/internal/index.js ***! \*******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getOptions: () => (/* reexport safe */ _options__WEBPACK_IMPORTED_MODULE_0__.getOptions), /* harmony export */ internal: () => (/* binding */ internal), /* harmony export */ setOptions: () => (/* reexport safe */ _options__WEBPACK_IMPORTED_MODULE_0__.setOptions), /* harmony export */ streamRequest: () => (/* reexport safe */ _streamRequest__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ xhrRequest: () => (/* reexport safe */ _xhrRequest__WEBPACK_IMPORTED_MODULE_2__["default"]) /* harmony export */ }); /* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./options */ 51500); /* harmony import */ var _streamRequest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./streamRequest */ 29643); /* harmony import */ var _xhrRequest__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./xhrRequest */ 43307); const internal = { xhrRequest: _xhrRequest__WEBPACK_IMPORTED_MODULE_2__["default"], streamRequest: _streamRequest__WEBPACK_IMPORTED_MODULE_1__["default"], setOptions: _options__WEBPACK_IMPORTED_MODULE_0__.setOptions, getOptions: _options__WEBPACK_IMPORTED_MODULE_0__.getOptions }; /***/ }, /***/ 51500 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/internal/options.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getOptions: () => (/* binding */ getOptions), /* harmony export */ setOptions: () => (/* binding */ setOptions) /* harmony export */ }); let options = { open(xhr, url) { xhr.open('get', url, true); }, beforeSend() {}, beforeProcessing(xhr) { return Promise.resolve(xhr.response); }, imageCreated() {}, strict: false }; function setOptions(newOptions) { options = Object.assign(options, newOptions); } function getOptions() { return options; } /***/ }, /***/ 29386 /*!**************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/internal/rangeRequest.js ***! \**************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ rangeRequest) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _wadors_extractMultipart__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../wadors/extractMultipart */ 59594); /* harmony import */ var _wadors_getImageQualityStatus__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../wadors/getImageQualityStatus */ 28993); /* harmony import */ var _wadors_metaDataManager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../wadors/metaDataManager */ 84237); /* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./options */ 51500); function rangeRequest(url, imageId, defaultHeaders = {}, options = {}) { const globalOptions = (0,_options__WEBPACK_IMPORTED_MODULE_4__.getOptions)(); const { retrieveOptions = {}, streamingData } = options; const chunkSize = streamingData.chunkSize || getValue(imageId, retrieveOptions, 'chunkSize') || 65_536; const errorInterceptor = error => { if (typeof globalOptions.errorInterceptor === 'function') { const error = new Error('request failed'); globalOptions.errorInterceptor(error); } else { console.warn('rangeRequest:Caught', error); } }; const promise = new Promise(/*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (resolve, reject) { const headers = Object.assign({}, defaultHeaders); for (const key of Object.keys(headers)) { if (headers[key] === null || headers[key] === undefined) { delete headers[key]; } } try { if (!streamingData.encodedData) { streamingData.chunkSize = chunkSize; streamingData.rangesFetched = 0; } const byteRange = getByteRange(streamingData, retrieveOptions); const { encodedData, responseHeaders } = yield fetchRangeAndAppend(url, headers, byteRange, streamingData); const contentType = responseHeaders.get('content-type'); const { totalBytes } = streamingData; const doneAllBytes = totalBytes === encodedData.byteLength; const extract = (0,_wadors_extractMultipart__WEBPACK_IMPORTED_MODULE_1__["default"])(contentType, encodedData, { isPartial: true }); const imageQualityStatus = (0,_wadors_getImageQualityStatus__WEBPACK_IMPORTED_MODULE_2__.getImageQualityStatus)(retrieveOptions, doneAllBytes || extract.extractDone); resolve({ ...extract, imageQualityStatus, percentComplete: extract.extractDone ? 100 : chunkSize * 100 / totalBytes }); } catch (error) { errorInterceptor(error); console.error(error); reject(error); } }); return function (_x, _x2) { return _ref.apply(this, arguments); }; }()); return promise; } function fetchRangeAndAppend(_x3, _x4, _x5, _x6) { return _fetchRangeAndAppend.apply(this, arguments); } function _fetchRangeAndAppend() { _fetchRangeAndAppend = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (url, headers, range, streamingData) { if (range) { headers = Object.assign(headers, { Range: `bytes=${range[0]}-${range[1]}` }); } let { encodedData } = streamingData; if (range[1] && encodedData?.byteLength > range[1]) { return streamingData; } const response = yield fetch(url, { headers, signal: undefined }); const responseArrayBuffer = yield response.arrayBuffer(); const responseTypedArray = new Uint8Array(responseArrayBuffer); const { status } = response; let newByteArray; if (encodedData) { newByteArray = new Uint8Array(encodedData.length + responseTypedArray.length); newByteArray.set(encodedData, 0); newByteArray.set(responseTypedArray, encodedData.length); streamingData.rangesFetched = 1; } else { newByteArray = new Uint8Array(responseTypedArray.length); newByteArray.set(responseTypedArray, 0); streamingData.rangesFetched++; } streamingData.encodedData = encodedData = newByteArray; streamingData.responseHeaders = response.headers; const contentRange = response.headers.get('Content-Range'); if (contentRange) { streamingData.totalBytes = Number(contentRange.split('/')[1]); } else if (status !== 206 || !range) { streamingData.totalBytes = encodedData?.byteLength; } else if (range[1] === '' || encodedData?.length < range[1]) { streamingData.totalBytes = encodedData.byteLength; } else { streamingData.totalBytes = Number.MAX_SAFE_INTEGER; } return streamingData; }); return _fetchRangeAndAppend.apply(this, arguments); } function getValue(imageId, source, attribute) { const value = source[attribute]; if (typeof value !== 'function') { return value; } const metaData = _wadors_metaDataManager__WEBPACK_IMPORTED_MODULE_3__["default"].get(imageId); return value(metaData, imageId); } function getByteRange(streamingData, retrieveOptions) { const { totalBytes, encodedData, chunkSize = 65_536 } = streamingData; const { rangeIndex = 0 } = retrieveOptions; if (rangeIndex === -1 && (!totalBytes || !encodedData)) { return [0, '']; } if (rangeIndex === -1 || encodedData?.byteLength > totalBytes - chunkSize) { return [encodedData?.byteLength || 0, '']; } return [encodedData?.byteLength || 0, chunkSize * (rangeIndex + 1) - 1]; } /***/ }, /***/ 29643 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/internal/streamRequest.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ streamRequest) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 80853); /* harmony import */ var _wadors_extractMultipart__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../wadors/extractMultipart */ 59594); /* harmony import */ var _wadors_getImageQualityStatus__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../wadors/getImageQualityStatus */ 28993); /* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./options */ 51500); const { ProgressiveIterator } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__; function streamRequest(url, imageId, defaultHeaders = {}, options = {}) { const globalOptions = (0,_options__WEBPACK_IMPORTED_MODULE_4__.getOptions)(); const { retrieveOptions = {}, streamingData = {} } = options; const minChunkSize = retrieveOptions.minChunkSize || 128 * 1024; const errorInterceptor = error => { if (typeof globalOptions.errorInterceptor === 'function') { const error = new Error('request failed'); globalOptions.errorInterceptor(error); } }; const loadIterator = new ProgressiveIterator('streamRequest'); loadIterator.generate(/*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (iterator, reject) { const beforeSendHeaders = globalOptions.beforeSend?.(null, url, defaultHeaders, {}); const headers = Object.assign({}, defaultHeaders, beforeSendHeaders); for (const key of Object.keys(headers)) { if (headers[key] === null) { headers[key] = undefined; } if (key === 'Accept' && url.includes('accept=')) { headers[key] = undefined; } } try { const response = yield fetch(url, { headers, signal: undefined }); if (response.status !== 200) { throw new Error(`Couldn't retrieve ${url} got status ${response.status}`); } const responseReader = response.body.getReader(); const responseHeaders = response.headers; const contentType = responseHeaders.get('content-type'); const totalBytes = Number(responseHeaders.get('Content-Length')); let readDone = false; let encodedData = streamingData.encodedData; let lastSize = streamingData.lastSize || 0; streamingData.isPartial = true; while (!readDone) { const { done, value } = yield responseReader.read(); encodedData = appendChunk(encodedData, value); if (!encodedData) { if (readDone) { throw new Error(`Done but no image frame available ${imageId}`); } continue; } readDone = done || encodedData.byteLength === totalBytes; if (!readDone && encodedData.length < lastSize + minChunkSize) { continue; } lastSize = encodedData.length; streamingData.isPartial = !done; const extracted = (0,_wadors_extractMultipart__WEBPACK_IMPORTED_MODULE_2__["default"])(contentType, encodedData, streamingData); const imageQualityStatus = (0,_wadors_getImageQualityStatus__WEBPACK_IMPORTED_MODULE_3__.getImageQualityStatus)(retrieveOptions, readDone); const detail = { url, imageId, ...extracted, percentComplete: done ? 100 : extracted.pixelData?.length * 100 / totalBytes, imageQualityStatus, done: readDone }; iterator.add(detail, readDone); } } catch (error) { errorInterceptor(error); console.error(error); reject(error); } }); return function (_x, _x2) { return _ref.apply(this, arguments); }; }()); return loadIterator.getNextPromise(); } function appendChunk(existing, chunk) { if (!existing) { return chunk; } if (!chunk) { return existing; } const newDataArray = new Uint8Array(existing.length + chunk.length); newDataArray.set(existing, 0); newDataArray.set(chunk, existing.length); return newDataArray; } /***/ }, /***/ 43307 /*!************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/internal/xhrRequest.js ***! \************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 28699); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 91133); /* harmony import */ var _options__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./options */ 51500); function xhrRequest(url, imageId, defaultHeaders = {}, parameters = {}) { const options = (0,_options__WEBPACK_IMPORTED_MODULE_2__.getOptions)(); const errorInterceptor = xhr => { if (typeof options.errorInterceptor === 'function') { const error = new Error('request failed'); error.request = xhr; error.response = xhr.response; error.status = xhr.status; options.errorInterceptor(error); } }; const xhr = new XMLHttpRequest(); const promise = new Promise((resolve, reject) => { options.open(xhr, url, defaultHeaders, parameters); const beforeSendHeaders = options.beforeSend(xhr, imageId, defaultHeaders, parameters); xhr.responseType = 'arraybuffer'; const headers = Object.assign({}, defaultHeaders, beforeSendHeaders); for (const key of Object.keys(headers)) { if (headers[key] === null) { continue; } if (key === 'Accept' && url.includes('accept=')) { continue; } xhr.setRequestHeader(key, headers[key]); } parameters.deferred = { resolve, reject }; parameters.url = url; parameters.imageId = imageId; xhr.addEventListener('loadstart', function (event) { if (options.onloadstart) { options.onloadstart(event, parameters); } const eventData = { url, imageId }; (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"], 'cornerstoneimageloadstart', eventData); }); xhr.onloadend = function (event) { if (options.onloadend) { options.onloadend(event, parameters); } const eventData = { url, imageId }; (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"], 'cornerstoneimageloadend', eventData); }; xhr.addEventListener('readystatechange', function (event) { if (options.onreadystatechange) { options.onreadystatechange(event, parameters); } if (xhr.readyState === 4) { if (xhr.status === 200 || xhr.status === 206) { options.beforeProcessing(xhr).then(resolve).catch(() => { errorInterceptor(xhr); reject(xhr); }); } else { errorInterceptor(xhr); reject(xhr); } } }); xhr.addEventListener('progress', function (oProgress) { const loaded = oProgress.loaded; let total; let percentComplete; if (oProgress.lengthComputable) { total = oProgress.total; percentComplete = Math.round(loaded / total * 100); } const eventData = { url, imageId, loaded, total, percentComplete }; (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__["default"], 'cornerstoneimageloadprogress', eventData); if (options.onprogress) { options.onprogress(oProgress, parameters); } }); xhr.onerror = function () { errorInterceptor(xhr); reject(xhr); }; xhr.addEventListener('abort', function () { errorInterceptor(xhr); reject(xhr); }); xhr.send(); }); promise.xhr = xhr; return promise; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (xhrRequest); /***/ }, /***/ 75056 /*!******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/isColorConversionRequired.js ***! \******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ isColorConversionRequired) /* harmony export */ }); function isColorConversionRequired(imageFrame) { if (imageFrame === undefined) { return false; } const { rows, columns, photometricInterpretation, pixelDataLength, planarConfiguration } = imageFrame; if (pixelDataLength === 4 * columns * rows) { return false; } if (photometricInterpretation === 'PALETTE COLOR') { return false; } if (photometricInterpretation.endsWith('420')) { return pixelDataLength === (3 * Math.ceil(columns / 2) + Math.floor(columns / 2)) * rows; } else if (photometricInterpretation.endsWith('422')) { return pixelDataLength === (3 * Math.ceil(columns / 2) + Math.floor(columns / 2)) * Math.ceil(rows / 2) + Math.floor(rows / 2) * columns; } else { return photometricInterpretation !== 'RGB' || planarConfiguration === 1; } } /***/ }, /***/ 23543 /*!****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/isJPEGBaseline8BitColor.js ***! \****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function isJPEGBaseline8BitColor(imageFrame, transferSyntax) { transferSyntax = transferSyntax || imageFrame.transferSyntax; if (imageFrame.bitsAllocated === 8 && transferSyntax === '1.2.840.10008.1.2.4.50' && (imageFrame.samplesPerPixel === 3 || imageFrame.samplesPerPixel === 4)) { return true; } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isJPEGBaseline8BitColor); /***/ }, /***/ 22561 /*!****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/isModalityLutForDisplay.js ***! \****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function isModalityLUTForDisplay(sopClassUid) { return sopClassUid !== '1.2.840.10008.5.1.4.1.1.12.1' && sopClassUid !== '1.2.840.10008.5.1.4.1.1.12.2.1'; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isModalityLUTForDisplay); /***/ }, /***/ 52819 /*!************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/isNMReconstructable.js ***! \************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ isNMReconstructable) /* harmony export */ }); function isNMReconstructable(imageSubType) { return imageSubType === 'RECON TOMO' || imageSubType === 'RECON GATED TOMO'; } /***/ }, /***/ 65173 /*!********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/registerLoaders.js ***! \********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _wadors_register__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./wadors/register */ 11812); /* harmony import */ var _wadouri_register__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wadouri/register */ 19095); function registerLoaders() { (0,_wadors_register__WEBPACK_IMPORTED_MODULE_0__["default"])(); (0,_wadouri_register__WEBPACK_IMPORTED_MODULE_1__["default"])(); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (registerLoaders); /***/ }, /***/ 7587 /*!********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/removeAFromRGBA.js ***! \********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function removeAFromRGBA(pixelData, targetBuffer) { const numberPixels = pixelData.length / 4; let rgbIndex = 0; let bufferIndex = 0; for (let index = 0; index < numberPixels; index++) { targetBuffer[bufferIndex++] = pixelData[rgbIndex++]; targetBuffer[bufferIndex++] = pixelData[rgbIndex++]; targetBuffer[bufferIndex++] = pixelData[rgbIndex++]; rgbIndex++; } return targetBuffer; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (removeAFromRGBA); /***/ }, /***/ 13956 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/setPixelDataType.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _shared_getPixelDataTypeFromMinMax__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../shared/getPixelDataTypeFromMinMax */ 52783); function setPixelDataType(imageFrame) { const minValue = imageFrame.smallestPixelValue; const maxValue = imageFrame.largestPixelValue; const TypedArray = (0,_shared_getPixelDataTypeFromMinMax__WEBPACK_IMPORTED_MODULE_0__["default"])(minValue, maxValue); if (TypedArray) { const typedArray = new TypedArray(imageFrame.pixelData); imageFrame.pixelData = typedArray; } else { throw new Error('Could not apply a typed array to the pixel data'); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (setPixelDataType); /***/ }, /***/ 62568 /*!********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/combineFrameInstance.js ***! \********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ combineFrameInstance: () => (/* binding */ combineFrameInstance), /* harmony export */ getFrameInformation: () => (/* binding */ getFrameInformation), /* harmony export */ getMultiframeInformation: () => (/* binding */ getMultiframeInformation) /* harmony export */ }); /* harmony import */ var _getTagValue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getTagValue */ 95888); function getFrameInformation(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frameNumber) { const shared = (SharedFunctionalGroupsSequence ? Object.values(SharedFunctionalGroupsSequence[0]) : []).map(it => it[0]).filter(it => it !== undefined && typeof it === 'object'); const perFrame = (PerFrameFunctionalGroupsSequence ? Object.values(PerFrameFunctionalGroupsSequence[frameNumber - 1]) : []).map(it => it.Value[0]).filter(it => it !== undefined && typeof it === 'object'); return { shared, perFrame }; } function getMultiframeInformation(metaData) { let { 52_009_230: PerFrameFunctionalGroupsSequence, 52_009_229: SharedFunctionalGroupsSequence, '00280008': NumberOfFrames, ...rest } = metaData; PerFrameFunctionalGroupsSequence = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_0__["default"])(PerFrameFunctionalGroupsSequence, false); SharedFunctionalGroupsSequence = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_0__["default"])(SharedFunctionalGroupsSequence, false); NumberOfFrames = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_0__["default"])(NumberOfFrames); return { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames, rest }; } function combineFrameInstance(frameNumber, instance) { const { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames, rest } = getMultiframeInformation(instance); if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) { const { shared, perFrame } = getFrameInformation(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frameNumber); const newInstance = Object.assign(instance, { frameNumber }); for (const item of [...shared, ...perFrame]) { for (const [key, value] of Object.entries(item)) { newInstance[key] = value; } } return Object.assign(rest, { '00280008': NumberOfFrames }, newInstance); } return instance; } /***/ }, /***/ 59594 /*!****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/extractMultipart.js ***! \****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ extractMultipart), /* harmony export */ findBoundary: () => (/* binding */ findBoundary), /* harmony export */ findContentType: () => (/* binding */ findContentType), /* harmony export */ uint8ArrayToString: () => (/* binding */ uint8ArrayToString) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var _findIndexOfString__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./findIndexOfString */ 6624); const { ImageQualityStatus } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; function extractMultipart(contentType, imageFrameAsArrayBuffer, options) { options ||= {}; const response = new Uint8Array(imageFrameAsArrayBuffer); const isPartial = !!options?.isPartial; if (!contentType.includes('multipart')) { return { contentType, imageQualityStatus: isPartial ? ImageQualityStatus.SUBRESOLUTION : ImageQualityStatus.FULL_RESOLUTION, pixelData: response }; } let { tokenIndex, responseHeaders, boundary, multipartContentType } = options; tokenIndex ||= (0,_findIndexOfString__WEBPACK_IMPORTED_MODULE_1__["default"])(response, '\r\n\r\n'); if (tokenIndex === -1) { throw new Error('invalid response - no multipart mime header'); } if (!boundary) { const header = uint8ArrayToString(response, 0, tokenIndex); responseHeaders = header.split('\r\n'); boundary = findBoundary(responseHeaders); if (!boundary) { throw new Error('invalid response - no boundary marker'); } } const offset = tokenIndex + 4; const endIndex = (0,_findIndexOfString__WEBPACK_IMPORTED_MODULE_1__["default"])(response, boundary, offset); if (endIndex === -1 && !isPartial) { throw new Error('invalid response - terminating boundary not found'); } multipartContentType ||= findContentType(responseHeaders); options.tokenIndex = tokenIndex; options.boundary = boundary; options.responseHeaders = responseHeaders; options.multipartContentType = multipartContentType; options.isPartial = endIndex === -1; return { contentType: multipartContentType, extractDone: !isPartial || endIndex !== -1, tokenIndex, responseHeaders, boundary, multipartContentType, pixelData: imageFrameAsArrayBuffer.slice(offset, endIndex - 2) }; } function findBoundary(header) { for (const element of header) { if (element.slice(0, 2) === '--') { return element; } } } function findContentType(header) { for (const element of header) { if (element.slice(0, 13) === 'Content-Type:') { return element.slice(13).trim(); } } } function uint8ArrayToString(data, offset, length) { offset = offset || 0; length = length || data.length - offset; let string_ = ''; for (let index = offset; index < offset + length; index++) { string_ += String.fromCharCode(data[index]); } return string_; } /***/ }, /***/ 6624 /*!*****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/findIndexOfString.js ***! \*****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function checkToken(token, data, dataOffset) { if (dataOffset + token.length > data.length) { return false; } let endIndex = dataOffset; for (const element of token) { if (element !== data[endIndex++]) { return false; } } return true; } function stringToUint8Array(string_) { const uint = new Uint8Array(string_.length); for (let index = 0, index_ = string_.length; index < index_; index++) { uint[index] = string_.charCodeAt(index); } return uint; } function findIndexOfString(data, string_, offset) { offset = offset || 0; const token = stringToUint8Array(string_); for (let index = offset; index < data.length; index++) { if (token[0] === data[index] && checkToken(token, data, index)) { return index; } } return -1; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (findIndexOfString); /***/ }, /***/ 28993 /*!*********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/getImageQualityStatus.js ***! \*********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getImageQualityStatus: () => (/* binding */ getImageQualityStatus) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); const { ImageQualityStatus } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; function getImageQualityStatus(retrieveOptions, done = true) { if (!done) { return ImageQualityStatus.SUBRESOLUTION; } return retrieveOptions.imageQualityStatus ?? ImageQualityStatus.FULL_RESOLUTION; } /***/ }, /***/ 61185 /*!************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/getPixelData.js ***! \************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _internal_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/index */ 52610); /* harmony import */ var _internal_rangeRequest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../internal/rangeRequest */ 29386); /* harmony import */ var _internal_streamRequest__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../internal/streamRequest */ 29643); /* harmony import */ var _extractMultipart__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./extractMultipart */ 59594); /* harmony import */ var _getImageQualityStatus__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./getImageQualityStatus */ 28993); function getPixelData(uri, imageId, mediaType = 'application/octet-stream', options) { const { streamingData, retrieveOptions = {} } = options || {}; const headers = { Accept: mediaType }; let url = retrieveOptions.urlArguments ? `${uri}${uri.includes('?') ? '&' : '?'}${retrieveOptions.urlArguments}` : uri; if (retrieveOptions.framesPath) { url = url.replace('/frames/', retrieveOptions.framesPath); } if (streamingData?.url !== url) { options.streamingData = { url }; } if (retrieveOptions.rangeIndex !== undefined) { return (0,_internal_rangeRequest__WEBPACK_IMPORTED_MODULE_1__["default"])(url, imageId, headers, options); } if (retrieveOptions.streaming) { return (0,_internal_streamRequest__WEBPACK_IMPORTED_MODULE_2__["default"])(url, imageId, headers, options); } const loadPromise = (0,_internal_index__WEBPACK_IMPORTED_MODULE_0__.xhrRequest)(url, imageId, headers); const { xhr } = loadPromise; return loadPromise.then(function (imageFrameAsArrayBuffer) { const contentType = xhr.getResponseHeader('Content-Type') || 'application/octet-stream'; const extracted = (0,_extractMultipart__WEBPACK_IMPORTED_MODULE_3__["default"])(contentType, new Uint8Array(imageFrameAsArrayBuffer)); extracted.imageQualityStatus = (0,_getImageQualityStatus__WEBPACK_IMPORTED_MODULE_4__.getImageQualityStatus)(retrieveOptions, true); return extracted; }); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getPixelData); /***/ }, /***/ 95888 /*!***********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/getTagValue.js ***! \***********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getTagValue) /* harmony export */ }); function getTagValue(tag, justElement = true) { if (tag && tag.Value) { if (tag.Value[0] && justElement) { return tag.Value[0]; } return tag.Value; } return tag; } /***/ }, /***/ 83973 /*!*****************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/index.js ***! \*****************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ findIndexOfString: () => (/* reexport safe */ _findIndexOfString__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ getPixelData: () => (/* reexport safe */ _getPixelData__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ loadImage: () => (/* reexport safe */ _loadImage__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ metaData: () => (/* binding */ metaData), /* harmony export */ metaDataManager: () => (/* reexport safe */ _metaDataManager__WEBPACK_IMPORTED_MODULE_8__["default"]), /* harmony export */ register: () => (/* reexport safe */ _register__WEBPACK_IMPORTED_MODULE_9__["default"]) /* harmony export */ }); /* harmony import */ var _findIndexOfString__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./findIndexOfString */ 6624); /* harmony import */ var _getPixelData__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getPixelData */ 61185); /* harmony import */ var _loadImage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./loadImage */ 82304); /* harmony import */ var _metaData_getNumberString__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metaData/getNumberString */ 38795); /* harmony import */ var _metaData_getNumberValue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./metaData/getNumberValue */ 73329); /* harmony import */ var _metaData_getNumberValues__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./metaData/getNumberValues */ 76868); /* harmony import */ var _metaData_getValue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./metaData/getValue */ 68306); /* harmony import */ var _metaData_metaDataProvider__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./metaData/metaDataProvider */ 77471); /* harmony import */ var _metaDataManager__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./metaDataManager */ 84237); /* harmony import */ var _register__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./register */ 11812); const metaData = { getNumberString: _metaData_getNumberString__WEBPACK_IMPORTED_MODULE_3__["default"], getNumberValue: _metaData_getNumberValue__WEBPACK_IMPORTED_MODULE_4__["default"], getNumberValues: _metaData_getNumberValues__WEBPACK_IMPORTED_MODULE_5__["default"], getValue: _metaData_getValue__WEBPACK_IMPORTED_MODULE_6__["default"], metaDataProvider: _metaData_metaDataProvider__WEBPACK_IMPORTED_MODULE_7__["default"] }; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ metaData, findIndexOfString: _findIndexOfString__WEBPACK_IMPORTED_MODULE_0__["default"], getPixelData: _getPixelData__WEBPACK_IMPORTED_MODULE_1__["default"], loadImage: _loadImage__WEBPACK_IMPORTED_MODULE_2__["default"], metaDataManager: _metaDataManager__WEBPACK_IMPORTED_MODULE_8__["default"], register: _register__WEBPACK_IMPORTED_MODULE_9__["default"] }); /***/ }, /***/ 82304 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/loadImage.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ getTransferSyntaxForContentType: () => (/* binding */ getTransferSyntaxForContentType) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncIterator_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncIterator.js */ 75105); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @cornerstonejs/core */ 85910); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @cornerstonejs/core */ 80853); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @cornerstonejs/core */ 9742); /* harmony import */ var _createImage__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../createImage */ 22555); /* harmony import */ var _getPixelData__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./getPixelData */ 61185); const { ProgressiveIterator } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_4__; const { ImageQualityStatus } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__; const streamableTransferSyntaxes = new Set(['1.2.840.10008.1.2.4.202', '1.2.840.10008.1.2.4.203', '3.2.840.10008.1.2.4.96']); function getTransferSyntaxForContentType(contentType) { const defaultTransferSyntax = '1.2.840.10008.1.2'; if (!contentType) { return defaultTransferSyntax; } const parameters = contentType.split(';'); const parameters_ = {}; for (const parameter of parameters) { const parameterValues = parameter.split('='); if (parameterValues.length !== 2) { continue; } const value = parameterValues[1].trim().replaceAll('"', ''); parameters_[parameterValues[0].trim()] = value; } const defaultTransferSyntaxByType = { 'image/jpeg': '1.2.840.10008.1.2.4.50', 'image/x-dicom-rle': '1.2.840.10008.1.2.5', 'image/x-jls': '1.2.840.10008.1.2.4.80', 'image/jls': '1.2.840.10008.1.2.4.80', 'image/jll': '1.2.840.10008.1.2.4.70', 'image/jp2': '1.2.840.10008.1.2.4.90', 'image/jpx': '1.2.840.10008.1.2.4.92', 'image/jphc': '3.2.840.10008.1.2.4.96', 'image/jxl': '1.2.840.10008.1.2.4.140' }; if (parameters_['transfer-syntax']) { return parameters_['transfer-syntax']; } else if (contentType && Object.keys(parameters_).length === 0 && defaultTransferSyntaxByType[contentType]) { return defaultTransferSyntaxByType[contentType]; } else if (parameters_.type && defaultTransferSyntaxByType[parameters_.type]) { return defaultTransferSyntaxByType[parameters_.type]; } else if (defaultTransferSyntaxByType[contentType]) { return defaultTransferSyntaxByType[contentType]; } return defaultTransferSyntax; } function getImageRetrievalPool() { return _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__["default"]; } const mediaType = 'multipart/related; type=application/octet-stream; transfer-syntax=*'; function loadImage(imageId, options = {}) { const imageRetrievalPool = getImageRetrievalPool(); const start = Date.now(); const uncompressedIterator = new ProgressiveIterator('decompress'); function sendXHR(_x, _x2, _x3) { return _sendXHR.apply(this, arguments); } function _sendXHR() { _sendXHR = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageURI, imageId, mediaType) { uncompressedIterator.generate(/*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (it) { const compressedIt = ProgressiveIterator.as((0,_getPixelData__WEBPACK_IMPORTED_MODULE_7__["default"])(imageURI, imageId, mediaType, options)); let lastDecodeLevel = 10; var _iteratorAbruptCompletion = false; var _didIteratorError = false; var _iteratorError; try { for (var _iterator = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncIterator_js__WEBPACK_IMPORTED_MODULE_1__["default"])(compressedIt), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) { const result = _step.value; { const { pixelData, imageQualityStatus = ImageQualityStatus.FULL_RESOLUTION, percentComplete, done = true, extractDone = true } = result; const transferSyntax = getTransferSyntaxForContentType(result.contentType); if (!extractDone && !streamableTransferSyntaxes.has(transferSyntax)) { continue; } const decodeLevel = result.decodeLevel ?? (imageQualityStatus === ImageQualityStatus.FULL_RESOLUTION ? 0 : decodeLevelFromComplete(percentComplete, options.retrieveOptions?.decodeLevel)); if (!done && lastDecodeLevel <= decodeLevel) { continue; } try { const useOptions = { ...options, decodeLevel }; const image = yield (0,_createImage__WEBPACK_IMPORTED_MODULE_6__["default"])(imageId, pixelData, transferSyntax, useOptions); const end = Date.now(); image.loadTimeInMS = end - start; image.transferSyntaxUID = transferSyntax; image.imageQualityStatus = imageQualityStatus; it.add(image, done); lastDecodeLevel = decodeLevel; } catch (error) { if (extractDone) { console.warn("Couldn't decode", error); throw error; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (_iteratorAbruptCompletion && _iterator.return != null) { yield _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } }); return function (_x4) { return _ref.apply(this, arguments); }; }()); }); return _sendXHR.apply(this, arguments); } const requestType = options.requestType || _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_5__["default"].Interaction; const additionalDetails = options.additionalDetails || { imageId }; const priority = options.priority === undefined ? 5 : options.priority; const uri = imageId.slice(7); imageRetrievalPool.addRequest(sendXHR.bind(this, uri, imageId, mediaType), requestType, additionalDetails, priority); return { promise: uncompressedIterator.getDonePromise(), cancelFn: undefined }; } function decodeLevelFromComplete(percent, retrieveDecodeLevel = 4) { const testSize = percent / 100 - 0.02; if (testSize > 1 / 4) { return Math.min(retrieveDecodeLevel, 0); } if (testSize > 1 / 16) { return Math.min(retrieveDecodeLevel, 1); } if (testSize > 1 / 64) { return Math.min(retrieveDecodeLevel, 2); } return Math.min(retrieveDecodeLevel, 3); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (loadImage); /***/ }, /***/ 53209 /*!******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/NMHelpers.js ***! \******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractOrientationFromNMMultiframeMetadata: () => (/* binding */ extractOrientationFromNMMultiframeMetadata), /* harmony export */ extractPositionFromNMMultiframeMetadata: () => (/* binding */ extractPositionFromNMMultiframeMetadata), /* harmony export */ getImageTypeSubItemFromMetadata: () => (/* binding */ getImageTypeSubItemFromMetadata), /* harmony export */ isNMModality: () => (/* binding */ isNMModality) /* harmony export */ }); /* harmony import */ var _isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../isNMReconstructable */ 52819); /* harmony import */ var _getTagValue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../getTagValue */ 95888); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getNumberValues */ 76868); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getValue */ 68306); function isNMModality(metaData) { const modality = (0,_getValue__WEBPACK_IMPORTED_MODULE_3__["default"])(metaData['00080060']); return modality.includes('NM'); } function getImageTypeSubItemFromMetadata(metaData, index) { const imageType = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData['00080008'], false); if (imageType) { return imageType[index]; } return; } function extractOrientationFromNMMultiframeMetadata(metaData) { let imageOrientationPatient; const imageSubType = getImageTypeSubItemFromMetadata(metaData, 2); if (imageSubType && (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__["default"])(imageSubType)) { const detectorInformationSequence = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData['00540022']); if (detectorInformationSequence) { imageOrientationPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_2__["default"])(detectorInformationSequence['00200037'], 6); } } return imageOrientationPatient; } function extractPositionFromNMMultiframeMetadata(metaData) { let imagePositionPatient; const imageSubType = getImageTypeSubItemFromMetadata(metaData, 2); if (imageSubType && (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__["default"])(imageSubType)) { const detectorInformationSequence = (0,_getTagValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData['00540022']); if (detectorInformationSequence) { imagePositionPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_2__["default"])(detectorInformationSequence['00200032'], 3); } } return imagePositionPatient; } /***/ }, /***/ 55914 /*!******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/USHelpers.js ***! \******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getUSEnhancedRegions: () => (/* binding */ getUSEnhancedRegions) /* harmony export */ }); /* harmony import */ var _getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getFirstNumberValue */ 95255); /* harmony import */ var _getSequenceItems__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getSequenceItems */ 33820); function getUSEnhancedRegions(metadata) { const sequenceOfUltrasoundRegions = (0,_getSequenceItems__WEBPACK_IMPORTED_MODULE_1__["default"])(metadata['00186011']); if (!sequenceOfUltrasoundRegions || sequenceOfUltrasoundRegions.length === 0) { return null; } const regions = sequenceOfUltrasoundRegions.map(sequence => { const physicalDeltaX = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018602C'); const physicalDeltaY = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018602E'); const physicalUnitsXDirection = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186024'); const physicalUnitsYDirection = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186026'); const regionLocationMinY0 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018601A'); const regionLocationMaxY1 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018601E'); const regionLocationMinX0 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186018'); const regionLocationMaxX1 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018601C'); const referencePixelX0 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186020'); const referencePixelY0 = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186022'); const referencePhysicalPixelValueY = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '0018602A'); const referencePhysicalPixelValueX = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186028'); const regionSpatialFormat = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186012'); const regionDataType = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186014'); const regionFlags = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186016'); const transducerFrequency = (0,_getFirstNumberValue__WEBPACK_IMPORTED_MODULE_0__.getFirstNumberValue)(sequence, '00186030'); return { regionLocationMinY0, regionLocationMaxY1, regionLocationMinX0, regionLocationMaxX1, referencePixelX0, referencePixelY0, physicalDeltaX, physicalDeltaY, physicalUnitsXDirection, physicalUnitsYDirection, referencePhysicalPixelValueY, referencePhysicalPixelValueX, regionSpatialFormat, regionDataType, regionFlags, transducerFrequency }; }); return regions; } /***/ }, /***/ 75292 /*!***************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/extractPositioningFromMetadata.js ***! \***************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractOrientationFromMetadata: () => (/* binding */ extractOrientationFromMetadata), /* harmony export */ extractPositionFromMetadata: () => (/* binding */ extractPositionFromMetadata) /* harmony export */ }); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getNumberValues */ 76868); /* harmony import */ var _NMHelpers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./NMHelpers */ 53209); function extractOrientationFromMetadata(metaData) { let imageOrientationPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData['00200037'], 6); if (!imageOrientationPatient && (0,_NMHelpers__WEBPACK_IMPORTED_MODULE_1__.isNMModality)(metaData)) { imageOrientationPatient = (0,_NMHelpers__WEBPACK_IMPORTED_MODULE_1__.extractOrientationFromNMMultiframeMetadata)(metaData); } return imageOrientationPatient; } function extractPositionFromMetadata(metaData) { let imagePositionPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData['00200032'], 3); if (!imagePositionPatient && (0,_NMHelpers__WEBPACK_IMPORTED_MODULE_1__.isNMModality)(metaData)) { imagePositionPatient = (0,_NMHelpers__WEBPACK_IMPORTED_MODULE_1__.extractPositionFromNMMultiframeMetadata)(metaData); } return imagePositionPatient; } /***/ }, /***/ 95255 /*!****************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getFirstNumberValue.js ***! \****************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getFirstNumberValue: () => (/* binding */ getFirstNumberValue) /* harmony export */ }); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getNumberValues */ 76868); function getFirstNumberValue(sequence, key) { const values = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_0__["default"])(sequence[key]); return values ? values[0] : null; } /***/ }, /***/ 38795 /*!************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getNumberString.js ***! \************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getValue */ 68306); function getNumberString(element, index, defaultValue) { const value = (0,_getValue__WEBPACK_IMPORTED_MODULE_0__["default"])(element, index, defaultValue); if (value === undefined) { return; } return Number.parseFloat(String(value)); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getNumberString); /***/ }, /***/ 73329 /*!***********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getNumberValue.js ***! \***********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getValue */ 68306); function getNumberValue(element, index) { const value = (0,_getValue__WEBPACK_IMPORTED_MODULE_0__["default"])(element, index); if (value === undefined) { return; } return Number.parseFloat(value); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getNumberValue); /***/ }, /***/ 76868 /*!************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getNumberValues.js ***! \************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getNumberValues(element, minimumLength) { if (!element) { return; } if (!element.Value) { return; } if (!Array.isArray(element.Value)) { return; } if (minimumLength && element.Value.length < minimumLength) { return; } const values = []; for (let index = 0; index < element.Value.length; index++) { values.push(Number.parseFloat(element.Value[index])); } return values; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getNumberValues); /***/ }, /***/ 32929 /*!******************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getOverlayPlaneModule.js ***! \******************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getOverlayPlaneModule) /* harmony export */ }); /* harmony import */ var _getNumberValue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getNumberValue */ 73329); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getValue */ 68306); function getOverlayPlaneModule(metaData) { const overlays = []; for (let overlayGroup = 0x00; overlayGroup <= 0x1e; overlayGroup += 0x02) { let groupString = `x60${overlayGroup.toString(16)}`; if (groupString.length === 4) { groupString = `x600${overlayGroup.toString(16)}`; } const data = (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}3000`]); if (!data) { continue; } const pixelData = []; for (let index = 0; index < data.length; index++) { for (let k = 0; k < 8; k++) { const byte_as_int = metaData.Value[data.dataOffset + index]; pixelData[index * 8 + k] = byte_as_int >> k & 0b1; } } overlays.push({ rows: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData[`${groupString}0010`]), columns: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData[`${groupString}0011`]), type: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}0040`]), x: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData[`${groupString}0050`], 1) - 1, y: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_0__["default"])(metaData[`${groupString}0050`], 0) - 1, pixelData, description: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}0022`]), label: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}1500`]), roiArea: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}1301`]), roiMean: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}1302`]), roiStandardDeviation: (0,_getValue__WEBPACK_IMPORTED_MODULE_1__["default"])(metaData[`${groupString}1303`]) }); } return { overlays }; } /***/ }, /***/ 33820 /*!*************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getSequenceItems.js ***! \*************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getSequenceItems(element) { if (!element?.Value?.length) { return []; } if (!Array.isArray(element.Value)) { if (typeof element.Value === 'object') { console.warn('Warning: Value should be an array, but an object was found. Encapsulating the object in an array.'); return [element.Value]; } return []; } return element.Value; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getSequenceItems); /***/ }, /***/ 68306 /*!*****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/getValue.js ***! \*****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getValue(element, index, defaultValue) { index = index || 0; if (!element) { return defaultValue; } if (!element.Value) { return defaultValue; } if (Array.isArray(element.Value) && element.Value.length <= index) { return defaultValue; } return element.Value[index]; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getValue); /***/ }, /***/ 50335 /*!**************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/index.js ***! \**************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getFirstNumberValue: () => (/* reexport safe */ _getFirstNumberValue__WEBPACK_IMPORTED_MODULE_5__.getFirstNumberValue), /* harmony export */ getNumberString: () => (/* reexport safe */ _getNumberString__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ getNumberValue: () => (/* reexport safe */ _getNumberValue__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ getNumberValues: () => (/* reexport safe */ _getNumberValues__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ getUSEnhancedRegions: () => (/* reexport safe */ _USHelpers__WEBPACK_IMPORTED_MODULE_6__.getUSEnhancedRegions), /* harmony export */ getValue: () => (/* reexport safe */ _getValue__WEBPACK_IMPORTED_MODULE_4__["default"]), /* harmony export */ metaDataProvider: () => (/* reexport safe */ _metaDataProvider__WEBPACK_IMPORTED_MODULE_3__["default"]) /* harmony export */ }); /* harmony import */ var _getNumberString__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getNumberString */ 38795); /* harmony import */ var _getNumberValue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getNumberValue */ 73329); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getNumberValues */ 76868); /* harmony import */ var _metaDataProvider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metaDataProvider */ 77471); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./getValue */ 68306); /* harmony import */ var _getFirstNumberValue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./getFirstNumberValue */ 95255); /* harmony import */ var _USHelpers__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./USHelpers */ 55914); /***/ }, /***/ 77471 /*!*************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaData/metaDataProvider.js ***! \*************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ getCineModule: () => (/* binding */ getCineModule), /* harmony export */ getImageUrlModule: () => (/* binding */ getImageUrlModule), /* harmony export */ getTransferSyntax: () => (/* binding */ getTransferSyntax) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 74654); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var _getInstanceModule__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../getInstanceModule */ 20645); /* harmony import */ var _isNMReconstructable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../isNMReconstructable */ 52819); /* harmony import */ var _combineFrameInstance__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../combineFrameInstance */ 62568); /* harmony import */ var _metaDataManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../metaDataManager */ 84237); /* harmony import */ var _extractPositioningFromMetadata__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./extractPositioningFromMetadata */ 75292); /* harmony import */ var _getNumberValue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./getNumberValue */ 73329); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./getNumberValues */ 76868); /* harmony import */ var _getOverlayPlaneModule__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./getOverlayPlaneModule */ 32929); /* harmony import */ var _getValue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./getValue */ 68306); /* harmony import */ var _NMHelpers__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./NMHelpers */ 53209); /* harmony import */ var _USHelpers__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./USHelpers */ 55914); function metaDataProvider(type, imageId) { const { MetadataModules } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; if (type === MetadataModules.MULTIFRAME) { const { metadata, frame } = (0,_metaDataManager__WEBPACK_IMPORTED_MODULE_6__.retrieveMultiframeMetadataImageId)(imageId); if (!metadata) { return; } const { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames } = (0,_combineFrameInstance__WEBPACK_IMPORTED_MODULE_5__.getMultiframeInformation)(metadata); if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) { const { shared, perFrame } = (0,_combineFrameInstance__WEBPACK_IMPORTED_MODULE_5__.getFrameInformation)(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frame); return { NumberOfFrames, PerFrameFunctionalInformation: perFrame, SharedFunctionalInformation: shared }; } return { NumberOfFrames }; } const metaData = _metaDataManager__WEBPACK_IMPORTED_MODULE_6__["default"].get(imageId); if (!metaData) { return; } if (type === MetadataModules.GENERAL_STUDY) { return { studyDescription: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00081030']), studyDate: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseDA((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080020'])), studyTime: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseTM((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080030'], 0, '')), accessionNumber: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080050']) }; } if (type === MetadataModules.GENERAL_SERIES) { return { modality: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080060']), seriesInstanceUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['0020000E']), seriesNumber: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00200011']), studyInstanceUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['0020000D']), seriesDate: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseDA((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080021'])), seriesTime: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseTM((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080031'], 0, '')), acquisitionDate: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseDA((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080022'])), acquisitionTime: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseTM((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080032'], 0, '')) }; } if (type === MetadataModules.GENERAL_IMAGE) { return { sopInstanceUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080018']), instanceNumber: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00200013']), lossyImageCompression: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00282110']), lossyImageCompressionRatio: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00282112']), lossyImageCompressionMethod: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00282114']) }; } if (type === MetadataModules.PATIENT) { return { patientID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00100020']), patientName: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00100010']) }; } if (type === MetadataModules.PATIENT_STUDY) { return { patientAge: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00101010']), patientSize: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00101020']), patientSex: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00100040']), patientWeight: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00101030']) }; } if (type === MetadataModules.NM_MULTIFRAME_GEOMETRY) { const modality = (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080060']); const imageSubType = (0,_NMHelpers__WEBPACK_IMPORTED_MODULE_12__.getImageTypeSubItemFromMetadata)(metaData, 2); return { modality, imageType: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080008']), imageSubType, imageOrientationPatient: (0,_extractPositioningFromMetadata__WEBPACK_IMPORTED_MODULE_7__.extractOrientationFromMetadata)(metaData), imagePositionPatient: (0,_extractPositioningFromMetadata__WEBPACK_IMPORTED_MODULE_7__.extractPositionFromMetadata)(metaData), sliceThickness: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00180050']), spacingBetweenSlices: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00180088']), pixelSpacing: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00280030'], 2), numberOfFrames: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280008']), isNMReconstructable: (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_4__["default"])(imageSubType) && modality.includes('NM') }; } if (type === MetadataModules.IMAGE_PLANE) { let imageOrientationPatient = (0,_extractPositioningFromMetadata__WEBPACK_IMPORTED_MODULE_7__.extractOrientationFromMetadata)(metaData); let imagePositionPatient = (0,_extractPositioningFromMetadata__WEBPACK_IMPORTED_MODULE_7__.extractPositionFromMetadata)(metaData); const pixelSpacing = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00280030'], 2); let columnPixelSpacing = null; let rowPixelSpacing = null; let rowCosines = null; let columnCosines = null; let usingDefaultValues = false; if (pixelSpacing) { rowPixelSpacing = pixelSpacing[0]; columnPixelSpacing = pixelSpacing[1]; } else { usingDefaultValues = true; rowPixelSpacing = 1; columnPixelSpacing = 1; } if (imageOrientationPatient) { rowCosines = [Number.parseFloat(imageOrientationPatient[0]), Number.parseFloat(imageOrientationPatient[1]), Number.parseFloat(imageOrientationPatient[2])]; columnCosines = [Number.parseFloat(imageOrientationPatient[3]), Number.parseFloat(imageOrientationPatient[4]), Number.parseFloat(imageOrientationPatient[5])]; } else { rowCosines = [1, 0, 0]; columnCosines = [0, 1, 0]; usingDefaultValues = true; imageOrientationPatient = [...rowCosines, ...columnCosines]; } if (!imagePositionPatient) { imagePositionPatient = [0, 0, 0]; usingDefaultValues = true; } return { frameOfReferenceUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00200052']), rows: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280010']), columns: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280011']), imageOrientationPatient, rowCosines, columnCosines, imagePositionPatient, sliceThickness: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00180050']), sliceLocation: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00201041']), pixelSpacing, rowPixelSpacing, columnPixelSpacing, usingDefaultValues }; } if (type === MetadataModules.ULTRASOUND_ENHANCED_REGION) { return (0,_USHelpers__WEBPACK_IMPORTED_MODULE_13__.getUSEnhancedRegions)(metaData); } if (type === MetadataModules.CALIBRATION) { const modality = (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080060']); if (modality === 'US') { const enhancedRegion = (0,_USHelpers__WEBPACK_IMPORTED_MODULE_13__.getUSEnhancedRegions)(metaData); return { sequenceOfUltrasoundRegions: enhancedRegion }; } } if (type === MetadataModules.IMAGE_URL) { return getImageUrlModule(imageId, metaData); } if (type === MetadataModules.CINE) { return getCineModule(imageId, metaData); } if (type === MetadataModules.IMAGE_PIXEL) { return { samplesPerPixel: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280002']), photometricInterpretation: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00280004']), rows: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280010']), columns: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280011']), bitsAllocated: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280100']), bitsStored: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280101']), highBit: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00280102']), pixelRepresentation: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280103']), planarConfiguration: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280006']), pixelAspectRatio: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00280034']), smallestPixelValue: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280106']), largestPixelValue: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280107']), redPaletteColorLookupTableDescriptor: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281101']), greenPaletteColorLookupTableDescriptor: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281102']), bluePaletteColorLookupTableDescriptor: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281103']), redPaletteColorLookupTableData: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281201']), greenPaletteColorLookupTableData: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281202']), bluePaletteColorLookupTableData: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281203']) }; } if (type === MetadataModules.VOI_LUT) { return { windowCenter: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281050'], 1), windowWidth: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_9__["default"])(metaData['00281051'], 1), voiLUTFunction: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00281056']) }; } if (type === MetadataModules.MODALITY_LUT) { return { rescaleIntercept: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00281052']), rescaleSlope: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00281053']), rescaleType: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00281054']) }; } if (type === MetadataModules.SOP_COMMON) { return { sopClassUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080016']), sopInstanceUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00080018']) }; } if (type === MetadataModules.PET_ISOTOPE) { const radiopharmaceuticalInfo = (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00540016']); if (radiopharmaceuticalInfo === undefined) { return; } return { radiopharmaceuticalInfo: { radiopharmaceuticalStartTime: dicom_parser__WEBPACK_IMPORTED_MODULE_2__.parseTM((0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(radiopharmaceuticalInfo['00181072'], 0, '')), radiopharmaceuticalStartDateTime: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(radiopharmaceuticalInfo['00181078'], 0, ''), radionuclideTotalDose: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(radiopharmaceuticalInfo['00181074']), radionuclideHalfLife: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(radiopharmaceuticalInfo['00181075']) } }; } if (type === MetadataModules.OVERLAY_PLANE) { return (0,_getOverlayPlaneModule__WEBPACK_IMPORTED_MODULE_10__["default"])(metaData); } if (type === 'transferSyntax') { return getTransferSyntax(imageId, metaData); } if (type === MetadataModules.PET_SERIES) { return { correctedImage: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00280051']), units: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00541001']), decayCorrection: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00541102']) }; } if (type === MetadataModules.PET_IMAGE) { return { frameReferenceTime: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00541300']), actualFrameDuration: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00181242']) }; } if (type === 'instance') { return (0,_getInstanceModule__WEBPACK_IMPORTED_MODULE_3__.getInstanceModule)(imageId, metaDataProvider, _getInstanceModule__WEBPACK_IMPORTED_MODULE_3__.instanceModuleNames); } } function getImageUrlModule(imageId, metaData) { const { transferSyntaxUID } = getTransferSyntax(imageId, metaData); const isVideo = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"](transferSyntaxUID); const imageUrl = imageId.slice(7); const thumbnail = imageUrl.replace('/frames/', '/thumbnail/'); let rendered = imageUrl.replace('/frames/', '/rendered/'); if (isVideo) { rendered = rendered.replace('/rendered/1', '/rendered'); } return { isVideo, rendered, thumbnail }; } function getCineModule(imageId, metaData) { const cineRate = (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00180040']); return { cineRate, numberOfFrames: (0,_getNumberValue__WEBPACK_IMPORTED_MODULE_8__["default"])(metaData['00280008']) }; } function getTransferSyntax(imageId, metaData) { return { transferSyntaxUID: (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00020010']) || (0,_getValue__WEBPACK_IMPORTED_MODULE_11__["default"])(metaData['00083002']) }; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (metaDataProvider); /***/ }, /***/ 84237 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/metaDataManager.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ isMultiframe: () => (/* binding */ isMultiframe), /* harmony export */ metadataByImageURI: () => (/* binding */ metadataByImageURI), /* harmony export */ retrieveMultiframeMetadataImageId: () => (/* binding */ retrieveMultiframeMetadataImageId) /* harmony export */ }); /* harmony import */ var _imageIdToURI__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../imageIdToURI */ 973); /* harmony import */ var _combineFrameInstance__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./combineFrameInstance */ 62568); /* harmony import */ var _metaData_getValue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./metaData/getValue */ 68306); let metadataByImageURI = []; let multiframeMetadataByImageURI = {}; function _retrieveMultiframeMetadataImageURI(imageURI) { const lastSlashIndex = imageURI.indexOf('/frames/') + 8; const imageIdFrameless = imageURI.slice(0, lastSlashIndex); const frame = Number.parseInt(imageURI.slice(lastSlashIndex), 10); const metadata = metadataByImageURI[`${imageIdFrameless}1`]; return { metadata, frame }; } function retrieveMultiframeMetadataImageId(imageId) { const imageURI = (0,_imageIdToURI__WEBPACK_IMPORTED_MODULE_0__["default"])(imageId); return _retrieveMultiframeMetadataImageURI(imageURI); } function isMultiframe(metadata) { const numberOfFrames = (0,_metaData_getValue__WEBPACK_IMPORTED_MODULE_2__["default"])(metadata['00280008']); return numberOfFrames && numberOfFrames > 1; } function add(imageId, metadata) { const imageURI = (0,_imageIdToURI__WEBPACK_IMPORTED_MODULE_0__["default"])(imageId); Object.defineProperty(metadata, 'isMultiframe', { value: isMultiframe(metadata), enumerable: false }); metadataByImageURI[imageURI] = metadata; } function get(imageId) { const imageURI = (0,_imageIdToURI__WEBPACK_IMPORTED_MODULE_0__["default"])(imageId); const metadata = metadataByImageURI[imageURI]; if (metadata && !metadata?.isMultiframe) { return metadata; } const cachedMetadata = multiframeMetadataByImageURI[imageURI]; if (cachedMetadata) { return cachedMetadata; } const retrievedMetadata = _retrieveMultiframeMetadataImageURI(imageURI); if (!retrievedMetadata || !retrievedMetadata.metadata) { return; } const { metadata: firstFrameMetadata, frame } = retrievedMetadata; if (firstFrameMetadata) { const combined = (0,_combineFrameInstance__WEBPACK_IMPORTED_MODULE_1__.combineFrameInstance)(frame, firstFrameMetadata); multiframeMetadataByImageURI[imageURI] = combined; return combined; } } function remove(imageId) { const imageURI = (0,_imageIdToURI__WEBPACK_IMPORTED_MODULE_0__["default"])(imageId); metadataByImageURI[imageURI] = undefined; multiframeMetadataByImageURI[imageURI] = undefined; } function purge() { metadataByImageURI = []; multiframeMetadataByImageURI = {}; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ add, get, remove, purge }); /***/ }, /***/ 11812 /*!********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadors/register.js ***! \********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 96035); /* harmony import */ var _loadImage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./loadImage */ 82304); /* harmony import */ var _metaData__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metaData */ 50335); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__() { (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.registerImageLoader)('wadors', _loadImage__WEBPACK_IMPORTED_MODULE_2__["default"]); _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__.addProvider(_metaData__WEBPACK_IMPORTED_MODULE_3__.metaDataProvider); } /***/ }, /***/ 47719 /*!****************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/combineFrameInstanceDataset.js ***! \****************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ combineFrameInstanceDataset: () => (/* binding */ combineFrameInstanceDataset), /* harmony export */ getDirectFrameInformation: () => (/* binding */ getDirectFrameInformation), /* harmony export */ getFrameInformation: () => (/* binding */ getFrameInformation), /* harmony export */ getMultiframeInformation: () => (/* binding */ getMultiframeInformation) /* harmony export */ }); function getDirectFrameInformation(dataSet, frame) { if (!dataSet) { return; } const { NumberOfFrames, PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence } = getMultiframeInformation(dataSet); if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) { const { shared, perFrame } = getFrameInformation(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frame); return { NumberOfFrames, PerFrameFunctionalInformation: perFrame, SharedFunctionalInformation: shared }; } return { NumberOfFrames }; } function getFrameInformation(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frameNumber) { const shared = {}; (SharedFunctionalGroupsSequence ? Object.values(SharedFunctionalGroupsSequence.items[0].dataSet.elements) : []).map(it => shared[it.tag] = it); const perFrame = {}; (PerFrameFunctionalGroupsSequence ? Object.values(PerFrameFunctionalGroupsSequence.items[frameNumber - 1].dataSet.elements) : []).map(it => perFrame[it.tag] = it); return { shared, perFrame }; } function getMultiframeInformation(dataSet) { if (!dataSet) { return; } const { elements, ...otherAttributtes } = dataSet; const { x52009230: PerFrameFunctionalGroupsSequence, x52009229: SharedFunctionalGroupsSequence, ...otherElements } = elements; const NumberOfFrames = dataSet.intString('x00280008'); return { NumberOfFrames, PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, otherElements, otherAttributtes }; } function combineFrameInstanceDataset(frameNumber, dataSet) { if (!dataSet) { return; } const { NumberOfFrames, PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, otherElements } = getMultiframeInformation(dataSet); if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) { const { shared, perFrame } = getFrameInformation(PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, frameNumber); const newElements = { elements: { ...otherElements, ...shared, ...perFrame } }; const clonedDataset = Object.create(dataSet); const newDataset = Object.assign(clonedDataset, newElements); return newDataset; } return dataSet; } /***/ }, /***/ 59201 /*!********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/dataSetCacheManager.js ***! \********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ getInfo: () => (/* binding */ getInfo), /* harmony export */ loadedDataSets: () => (/* reexport safe */ _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 28699); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 91133); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var _internal_index__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../internal/index */ 52610); /* harmony import */ var _combineFrameInstanceDataset__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./combineFrameInstanceDataset */ 47719); /* harmony import */ var _dataset_from_partial_content__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./dataset-from-partial-content */ 28777); /* harmony import */ var _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./loadedDataSets */ 30826); /* harmony import */ var _retrieveMultiframeDataset__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./retrieveMultiframeDataset */ 46526); let cacheSizeInBytes = 0; let promises = {}; function isLoaded(uri) { return _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri] !== undefined; } function get(uri) { let dataSet; if (uri.includes('&frame=')) { const { frame, dataSet: multiframeDataSet } = _retrieveMultiframeDataset__WEBPACK_IMPORTED_MODULE_8__["default"].retrieveMultiframeDataset(uri); dataSet = (0,_combineFrameInstanceDataset__WEBPACK_IMPORTED_MODULE_5__.combineFrameInstanceDataset)(frame, multiframeDataSet); } else if (_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri]) { dataSet = _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].dataSet; } return dataSet; } function update(uri, dataSet) { const loadedDataSet = _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri]; if (!loadedDataSet) { console.error(`No loaded dataSet for uri ${uri}`); return; } cacheSizeInBytes -= loadedDataSet.dataSet.byteArray.length; loadedDataSet.dataSet = dataSet; cacheSizeInBytes += dataSet.byteArray.length; (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"], 'datasetscachechanged', { uri, action: 'updated', cacheInfo: getInfo() }); } function load(uri, loadRequest = _internal_index__WEBPACK_IMPORTED_MODULE_4__.xhrRequest, imageId) { if (_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri]) { return new Promise(resolve => { _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].cacheCount++; resolve(_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].dataSet); }); } if (promises[uri]) { promises[uri].cacheCount++; return promises[uri]; } const loadDICOMPromise = loadRequest(uri, imageId); const promise = new Promise((resolve, reject) => { loadDICOMPromise.then(/*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (dicomPart10AsArrayBuffer) { const partialContent = { isPartialContent: false, fileTotalLength: null }; if (!(dicomPart10AsArrayBuffer instanceof ArrayBuffer)) { if (!dicomPart10AsArrayBuffer.arrayBuffer) { return reject(new Error('If not returning ArrayBuffer, must return object with `arrayBuffer` parameter')); } partialContent.isPartialContent = dicomPart10AsArrayBuffer.flags.isPartialContent; partialContent.fileTotalLength = dicomPart10AsArrayBuffer.flags.fileTotalLength; dicomPart10AsArrayBuffer = dicomPart10AsArrayBuffer.arrayBuffer; } const byteArray = new Uint8Array(dicomPart10AsArrayBuffer); let dataSet; try { dataSet = partialContent.isPartialContent ? yield (0,_dataset_from_partial_content__WEBPACK_IMPORTED_MODULE_6__["default"])(byteArray, loadRequest, { uri, imageId, fileTotalLength: partialContent.fileTotalLength }) : dicom_parser__WEBPACK_IMPORTED_MODULE_3__.parseDicom(byteArray); } catch (error) { return reject(error); } _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri] = { dataSet, cacheCount: promise.cacheCount }; cacheSizeInBytes += dataSet.byteArray.length; resolve(dataSet); (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"], 'datasetscachechanged', { uri, action: 'loaded', cacheInfo: getInfo() }); }); return function (_x) { return _ref.apply(this, arguments); }; }(), reject).then(() => { delete promises[uri]; }, () => { delete promises[uri]; }); }); promise.cacheCount = 1; promises[uri] = promise; return promise; } function unload(uri) { if (_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri]) { _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].cacheCount--; if (_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].cacheCount === 0) { cacheSizeInBytes -= _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri].dataSet.byteArray.length; delete _loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets[uri]; (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__["default"])(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__["default"], 'datasetscachechanged', { uri, action: 'unloaded', cacheInfo: getInfo() }); } } } function getInfo() { return { cacheSizeInBytes, numberOfDataSetsCached: Object.keys(_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.loadedDataSets).length }; } function purge() { (0,_loadedDataSets__WEBPACK_IMPORTED_MODULE_7__.purgeLoadedDataSets)(); promises = {}; cacheSizeInBytes = 0; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ isLoaded, load, unload, getInfo, purge, get, update }); /***/ }, /***/ 28777 /*!*****************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/dataset-from-partial-content.js ***! \*****************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ dataSetFromPartialContent) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! dicom-parser */ 99564); function fixFragments(dataSet) { const fragments = dataSet.elements.x7fe00010.fragments; const totalLength = dataSet.byteArray.length; for (const fragment of fragments) { const { position, length } = fragment; if (length > totalLength - position) { console.log(`Truncated fragment, changing fragment length from ${fragment.length} to ${totalLength - position}`); fragment.length = totalLength - position; } } return dataSet; } function parsePartialByteArray(byteArray) { let dataSet = dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseDicom(byteArray, { untilTag: 'x7fe00010' }); if (!dataSet.elements.x7fe00010) { console.warn('Pixel data not found!'); } let pixelDataSet; try { pixelDataSet = dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseDicom(byteArray); } catch (error) { console.error(error); console.log('pixel data dataset:', error.dataSet); pixelDataSet = error.dataSet; } dataSet.elements.x7fe00010 = pixelDataSet.elements.x7fe00010; dataSet = fixFragments(dataSet); return dataSet; } function dataSetFromPartialContent(_x, _x2, _x3) { return _dataSetFromPartialContent.apply(this, arguments); } function _dataSetFromPartialContent() { _dataSetFromPartialContent = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (byteArray, loadRequest, metadata) { const dataSet = parsePartialByteArray(byteArray); const { uri, imageId, fileTotalLength } = metadata; dataSet.fetchMore = /*#__PURE__*/function () { var _ref = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (fetchOptions) { const _options = Object.assign({ uri, imageId, fetchedLength: byteArray.length, lengthToFetch: fileTotalLength - byteArray.length }, fetchOptions); const { fetchedLength, lengthToFetch } = _options; const { arrayBuffer } = yield loadRequest(uri, imageId, { byteRange: `${fetchedLength}-${fetchedLength + lengthToFetch}` }); const byteArrayToAppend = new Uint8Array(arrayBuffer); const combinedByteArray = new Uint8Array(dataSet.byteArray.length + byteArrayToAppend.length); combinedByteArray.set(dataSet.byteArray); combinedByteArray.set(byteArrayToAppend, dataSet.byteArray.length); return dataSetFromPartialContent(combinedByteArray, loadRequest, metadata); }); return function (_x4) { return _ref.apply(this, arguments); }; }(); return dataSet; }); return _dataSetFromPartialContent.apply(this, arguments); } /***/ }, /***/ 22237 /*!************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/fileManager.js ***! \************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); let files = []; function add(file) { const fileIndex = files.push(file); return `dicomfile:${fileIndex - 1}`; } function get(index) { return files[index]; } function remove(index) { files[index] = undefined; } function purge() { files = []; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ add, get, remove, purge }); /***/ }, /***/ 53029 /*!**************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/getEncapsulatedImageFrame.js ***! \**************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getEncapsulatedImageFrame) /* harmony export */ }); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dicom-parser */ 99564); function framesAreFragmented(dataSet) { const numberOfFrames = dataSet.intString('x00280008'); const pixelDataElement = dataSet.elements.x7fe00010; return numberOfFrames !== pixelDataElement.fragments.length; } function getEncapsulatedImageFrame(dataSet, frameIndex) { if (dataSet.elements.x7fe00010 && dataSet.elements.x7fe00010.basicOffsetTable.length > 0) { return dicom_parser__WEBPACK_IMPORTED_MODULE_0__.readEncapsulatedImageFrame(dataSet, dataSet.elements.x7fe00010, frameIndex); } if (framesAreFragmented(dataSet)) { const basicOffsetTable = dicom_parser__WEBPACK_IMPORTED_MODULE_0__.createJPEGBasicOffsetTable(dataSet, dataSet.elements.x7fe00010); return dicom_parser__WEBPACK_IMPORTED_MODULE_0__.readEncapsulatedImageFrame(dataSet, dataSet.elements.x7fe00010, frameIndex, basicOffsetTable); } const fragments = dataSet.elements.x7fe00010.fragments; const byteStream = new dicom_parser__WEBPACK_IMPORTED_MODULE_0__.ByteStream(dataSet.byteArrayParser, dataSet.byteArray, dataSet.elements.x7fe00010.dataOffset); const basicOffsetTable = dicom_parser__WEBPACK_IMPORTED_MODULE_0__.readSequenceItem(byteStream); if (basicOffsetTable.tag !== 'xfffee000') { throw 'dicomParser.readEncapsulatedPixelData: missing basic offset table xfffee000'; } byteStream.seek(basicOffsetTable.length); const fragmentZeroPosition = byteStream.position; if (frameIndex + 1 > fragments.length) { throw 'dicomParser.readEncapsulatedPixelData: frame exceeds number of fragments'; } const fragmentHeaderSize = 8; const byteOffset = fragmentZeroPosition + fragments[frameIndex].offset + fragmentHeaderSize; const length = fragments[frameIndex].length; return new Uint8Array(byteStream.byteArray.buffer.slice(byteStream.byteArray.byteOffset + byteOffset, byteStream.byteArray.byteOffset + byteOffset + length)); } /***/ }, /***/ 51678 /*!*************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/getPixelData.js ***! \*************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _getEncapsulatedImageFrame__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getEncapsulatedImageFrame */ 53029); /* harmony import */ var _getUncompressedImageFrame__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getUncompressedImageFrame */ 97408); function getPixelData(dataSet, frameIndex = 0) { const pixelDataElement = dataSet.elements.x7fe00010 || dataSet.elements.x7fe00008; if (!pixelDataElement) { return null; } if (pixelDataElement.encapsulatedPixelData) { return (0,_getEncapsulatedImageFrame__WEBPACK_IMPORTED_MODULE_0__["default"])(dataSet, frameIndex); } return (0,_getUncompressedImageFrame__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet, frameIndex); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getPixelData); /***/ }, /***/ 97408 /*!**************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/getUncompressedImageFrame.js ***! \**************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _unpackBinaryFrame__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./unpackBinaryFrame */ 57612); function getUncompressedImageFrame(dataSet, frameIndex) { const pixelDataElement = dataSet.elements.x7fe00010 || dataSet.elements.x7fe00008; const bitsAllocated = dataSet.uint16('x00280100'); const rows = dataSet.uint16('x00280010'); const columns = dataSet.uint16('x00280011'); let samplesPerPixel = dataSet.uint16('x00280002'); const photometricInterpretation = dataSet.string('x00280004'); if (photometricInterpretation === 'YBR_FULL_422') { samplesPerPixel = 2; console.warn(`Using SamplesPerPixel of 2 for YBR_FULL_422 photometric interpretation. See http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.3.html for more information.`); } const pixelDataOffset = pixelDataElement.dataOffset; const pixelsPerFrame = rows * columns * samplesPerPixel; let frameOffset; switch (bitsAllocated) { case 1: { frameOffset = pixelDataOffset + frameIndex * pixelsPerFrame * 0.125; if (frameOffset >= dataSet.byteArray.length) { throw new Error('frame exceeds size of pixelData'); } return (0,_unpackBinaryFrame__WEBPACK_IMPORTED_MODULE_0__["default"])(dataSet.byteArray, frameOffset, pixelsPerFrame); } case 16: { frameOffset = pixelDataOffset + frameIndex * pixelsPerFrame * 2; if (frameOffset >= dataSet.byteArray.length) { throw new Error('frame exceeds size of pixelData'); } return new Uint8Array(dataSet.byteArray.buffer.slice(frameOffset, frameOffset + pixelsPerFrame * 2)); } case 32: { frameOffset = pixelDataOffset + frameIndex * pixelsPerFrame * 4; if (frameOffset >= dataSet.byteArray.length) { throw new Error('frame exceeds size of pixelData'); } return new Uint8Array(dataSet.byteArray.buffer.slice(frameOffset, frameOffset + pixelsPerFrame * 4)); } case 8: { frameOffset = pixelDataOffset + frameIndex * pixelsPerFrame; if (frameOffset >= dataSet.byteArray.length) { throw new Error('frame exceeds size of pixelData'); } return new Uint8Array(dataSet.byteArray.buffer.slice(frameOffset, frameOffset + pixelsPerFrame)); } // No default } throw new Error('unsupported pixel format'); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getUncompressedImageFrame); /***/ }, /***/ 67816 /*!******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/index.js ***! \******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ dataSetCacheManager: () => (/* reexport safe */ _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ fileManager: () => (/* reexport safe */ _fileManager__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ getEncapsulatedImageFrame: () => (/* reexport safe */ _getEncapsulatedImageFrame__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ getLoaderForScheme: () => (/* reexport safe */ _loadImage__WEBPACK_IMPORTED_MODULE_6__.getLoaderForScheme), /* harmony export */ getPixelData: () => (/* reexport safe */ _getPixelData__WEBPACK_IMPORTED_MODULE_3__["default"]), /* harmony export */ getUncompressedImageFrame: () => (/* reexport safe */ _getUncompressedImageFrame__WEBPACK_IMPORTED_MODULE_4__["default"]), /* harmony export */ loadFileRequest: () => (/* reexport safe */ _loadFileRequest__WEBPACK_IMPORTED_MODULE_5__["default"]), /* harmony export */ loadImage: () => (/* reexport safe */ _loadImage__WEBPACK_IMPORTED_MODULE_6__.loadImage), /* harmony export */ loadImageFromPromise: () => (/* reexport safe */ _loadImage__WEBPACK_IMPORTED_MODULE_6__.loadImageFromPromise), /* harmony export */ metaData: () => (/* binding */ metaData), /* harmony export */ parseImageId: () => (/* reexport safe */ _parseImageId__WEBPACK_IMPORTED_MODULE_8__["default"]), /* harmony export */ register: () => (/* reexport safe */ _register__WEBPACK_IMPORTED_MODULE_9__["default"]), /* harmony export */ unpackBinaryFrame: () => (/* reexport safe */ _unpackBinaryFrame__WEBPACK_IMPORTED_MODULE_10__["default"]) /* harmony export */ }); /* harmony import */ var _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./dataSetCacheManager */ 59201); /* harmony import */ var _fileManager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./fileManager */ 22237); /* harmony import */ var _getEncapsulatedImageFrame__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getEncapsulatedImageFrame */ 53029); /* harmony import */ var _getPixelData__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getPixelData */ 51678); /* harmony import */ var _getUncompressedImageFrame__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./getUncompressedImageFrame */ 97408); /* harmony import */ var _loadFileRequest__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./loadFileRequest */ 67183); /* harmony import */ var _loadImage__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./loadImage */ 73321); /* harmony import */ var _metaData_index__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./metaData/index */ 67960); /* harmony import */ var _parseImageId__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./parseImageId */ 59875); /* harmony import */ var _register__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./register */ 19095); /* harmony import */ var _unpackBinaryFrame__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./unpackBinaryFrame */ 57612); const metaData = { getImagePixelModule: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.getImagePixelModule, getLUTs: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.getLUTs, getModalityLUTOutputPixelRepresentation: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.getModalityLUTOutputPixelRepresentation, getNumberValues: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.getNumberValues, metaDataProvider: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.metaDataProvider, metadataForDataset: _metaData_index__WEBPACK_IMPORTED_MODULE_7__.metadataForDataset }; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ metaData, dataSetCacheManager: _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_0__["default"], fileManager: _fileManager__WEBPACK_IMPORTED_MODULE_1__["default"], getEncapsulatedImageFrame: _getEncapsulatedImageFrame__WEBPACK_IMPORTED_MODULE_2__["default"], getUncompressedImageFrame: _getUncompressedImageFrame__WEBPACK_IMPORTED_MODULE_4__["default"], loadFileRequest: _loadFileRequest__WEBPACK_IMPORTED_MODULE_5__["default"], loadImageFromPromise: _loadImage__WEBPACK_IMPORTED_MODULE_6__.loadImageFromPromise, getLoaderForScheme: _loadImage__WEBPACK_IMPORTED_MODULE_6__.getLoaderForScheme, getPixelData: _getPixelData__WEBPACK_IMPORTED_MODULE_3__["default"], loadImage: _loadImage__WEBPACK_IMPORTED_MODULE_6__.loadImage, parseImageId: _parseImageId__WEBPACK_IMPORTED_MODULE_8__["default"], unpackBinaryFrame: _unpackBinaryFrame__WEBPACK_IMPORTED_MODULE_10__["default"], register: _register__WEBPACK_IMPORTED_MODULE_9__["default"] }); /***/ }, /***/ 67183 /*!****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/loadFileRequest.js ***! \****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _fileManager__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./fileManager */ 22237); /* harmony import */ var _parseImageId__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./parseImageId */ 59875); function loadFileRequest(uri) { const parsedImageId = (0,_parseImageId__WEBPACK_IMPORTED_MODULE_1__["default"])(uri); const fileIndex = Number.parseInt(parsedImageId.url, 10); const file = _fileManager__WEBPACK_IMPORTED_MODULE_0__["default"].get(fileIndex); return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.addEventListener('load', e => { const dicomPart10AsArrayBuffer = e.target.result; resolve(dicomPart10AsArrayBuffer); }); fileReader.onerror = reject; fileReader.readAsArrayBuffer(file); }); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (loadFileRequest); /***/ }, /***/ 73321 /*!**********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/loadImage.js ***! \**********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getLoaderForScheme: () => (/* binding */ getLoaderForScheme), /* harmony export */ loadImage: () => (/* binding */ loadImage), /* harmony export */ loadImageFromPromise: () => (/* binding */ loadImageFromPromise) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var _createImage__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../createImage */ 22555); /* harmony import */ var _internal_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../internal/index */ 52610); /* harmony import */ var _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./dataSetCacheManager */ 59201); /* harmony import */ var _getPixelData__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./getPixelData */ 51678); /* harmony import */ var _loadFileRequest__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./loadFileRequest */ 67183); /* harmony import */ var _parseImageId__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./parseImageId */ 59875); const { ImageQualityStatus } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; function addDecache(imageLoadObject, imageId) { imageLoadObject.decache = function () { const parsedImageId = (0,_parseImageId__WEBPACK_IMPORTED_MODULE_6__["default"])(imageId); _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_3__["default"].unload(parsedImageId.url); }; } function loadImageFromPromise(dataSetPromise, imageId, frame = 0, sharedCacheKey, options, callbacks) { const start = Date.now(); const imageLoadObject = { cancelFn: undefined, promise: undefined }; imageLoadObject.promise = new Promise((resolve, reject) => { dataSetPromise.then(dataSet => { const pixelData = (0,_getPixelData__WEBPACK_IMPORTED_MODULE_4__["default"])(dataSet, frame); const transferSyntax = dataSet.string('x00020010'); const loadEnd = Date.now(); const imagePromise = (0,_createImage__WEBPACK_IMPORTED_MODULE_1__["default"])(imageId, pixelData, transferSyntax, options); addDecache(imageLoadObject, imageId); imagePromise.then(image => { image = image; image.data = dataSet; image.sharedCacheKey = sharedCacheKey; const end = Date.now(); image.loadTimeInMS = loadEnd - start; image.totalTimeInMS = end - start; image.imageQualityStatus = ImageQualityStatus.FULL_RESOLUTION; if (callbacks !== undefined && callbacks.imageDoneCallback !== undefined) { callbacks.imageDoneCallback(image); } resolve(image); }, function (error) { reject({ error, dataSet }); }); }, function (error) { reject({ error }); }); }); return imageLoadObject; } function loadImageFromDataSet(dataSet, imageId, frame = 0, sharedCacheKey, options) { const start = Date.now(); const promise = new Promise((resolve, reject) => { const loadEnd = Date.now(); let imagePromise; try { const pixelData = (0,_getPixelData__WEBPACK_IMPORTED_MODULE_4__["default"])(dataSet, frame); const transferSyntax = dataSet.string('x00020010'); imagePromise = (0,_createImage__WEBPACK_IMPORTED_MODULE_1__["default"])(imageId, pixelData, transferSyntax, options); } catch (error) { reject({ error, dataSet }); return; } imagePromise.then(image => { image = image; image.data = dataSet; image.sharedCacheKey = sharedCacheKey; const end = Date.now(); image.loadTimeInMS = loadEnd - start; image.totalTimeInMS = end - start; image.imageQualityStatus = ImageQualityStatus.FULL_RESOLUTION; resolve(image); }, reject); }); return { promise: promise, cancelFn: undefined }; } function getLoaderForScheme(scheme) { if (scheme === 'dicomweb' || scheme === 'wadouri') { return _internal_index__WEBPACK_IMPORTED_MODULE_2__.xhrRequest; } else if (scheme === 'dicomfile') { return _loadFileRequest__WEBPACK_IMPORTED_MODULE_5__["default"]; } } function loadImage(imageId, options = {}) { const parsedImageId = (0,_parseImageId__WEBPACK_IMPORTED_MODULE_6__["default"])(imageId); options = Object.assign({}, options); delete options.loader; const schemeLoader = getLoaderForScheme(parsedImageId.scheme); if (_dataSetCacheManager__WEBPACK_IMPORTED_MODULE_3__["default"].isLoaded(parsedImageId.url)) { const dataSet = _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_3__["default"].get(parsedImageId.url, schemeLoader, imageId); return loadImageFromDataSet(dataSet, imageId, parsedImageId.pixelDataFrame, parsedImageId.url, options); } const dataSetPromise = _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_3__["default"].load(parsedImageId.url, schemeLoader, imageId); return loadImageFromPromise(dataSetPromise, imageId, parsedImageId.frame, parsedImageId.url, options); } /***/ }, /***/ 30826 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/loadedDataSets.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ loadedDataSets: () => (/* binding */ loadedDataSets), /* harmony export */ purgeLoadedDataSets: () => (/* binding */ purgeLoadedDataSets) /* harmony export */ }); let loadedDataSets = {}; const purgeLoadedDataSets = () => { loadedDataSets = {}; }; /***/ }, /***/ 65977 /*!*******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/USHelpers.js ***! \*******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getUSEnhancedRegions: () => (/* binding */ getUSEnhancedRegions) /* harmony export */ }); function getUSEnhancedRegions(metadata) { const sequence = metadata.elements['x00186011']; if (!sequence || !sequence.items) { return []; } const regions = sequence.items.map(item => { const physicalDeltaX = item.dataSet.double('x0018602c'); const physicalDeltaY = item.dataSet.double('x0018602e'); const physicalUnitsXDirection = item.dataSet.uint16('x00186024'); const physicalUnitsYDirection = item.dataSet.uint16('x00186026'); const regionLocationMinY0 = item.dataSet.uint16('x0018601a'); const regionLocationMaxY1 = item.dataSet.uint16('x0018601e'); const regionLocationMinX0 = item.dataSet.uint16('x00186018'); const regionLocationMaxX1 = item.dataSet.uint16('x0018601c'); const referencePixelX0 = item.dataSet.int32('x00186020') || null; const referencePixelY0 = item.dataSet.int32('x00186022') || null; const referencePhysicalPixelValueY = item.dataSet.uint16('x0018602a'); const referencePhysicalPixelValueX = item.dataSet.uint16('x00186028'); const regionSpatialFormat = item.dataSet.uint16('x00186012'); const regionDataType = item.dataSet.uint16('x00186014'); const regionFlags = item.dataSet.uint16('x00186016'); const transducerFrequency = item.dataSet.uint16('x00186030'); return { regionLocationMinY0, regionLocationMaxY1, regionLocationMinX0, regionLocationMaxX1, referencePixelX0, referencePixelY0, physicalDeltaX, physicalDeltaY, physicalUnitsXDirection, physicalUnitsYDirection, referencePhysicalPixelValueY, referencePhysicalPixelValueX, regionSpatialFormat, regionDataType, regionFlags, transducerFrequency }; }); return regions; } /***/ }, /***/ 88346 /*!***************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/extractPositioningFromDataset.js ***! \***************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ extractOrientationFromDataset: () => (/* binding */ extractOrientationFromDataset), /* harmony export */ extractPositionFromDataset: () => (/* binding */ extractPositionFromDataset), /* harmony export */ extractSliceThicknessFromDataset: () => (/* binding */ extractSliceThicknessFromDataset), /* harmony export */ extractSpacingFromDataset: () => (/* binding */ extractSpacingFromDataset), /* harmony export */ getImageTypeSubItemFromDataset: () => (/* binding */ getImageTypeSubItemFromDataset) /* harmony export */ }); /* harmony import */ var _isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../isNMReconstructable */ 52819); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getNumberValues */ 92939); function getImageTypeSubItemFromDataset(dataSet, index) { const imageType = dataSet.string('x00080008'); if (imageType) { const subTypes = imageType.split('\\'); if (subTypes.length > index) { return subTypes[index]; } } return; } function extractOrientationFromNMMultiframeDataset(dataSet) { let imageOrientationPatient; const modality = dataSet.string('x00080060'); if (modality?.includes('NM')) { const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2); if (imageSubType && (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__["default"])(imageSubType) && dataSet.elements.x00540022) { imageOrientationPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet.elements.x00540022.items[0].dataSet, 'x00200037', 6); } } return imageOrientationPatient; } function extractPositionFromNMMultiframeDataset(dataSet) { let imagePositionPatient; const modality = dataSet.string('x00080060'); if (modality?.includes('NM')) { const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2); if (imageSubType && (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_0__["default"])(imageSubType) && dataSet.elements.x00540022) { imagePositionPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet.elements.x00540022.items[0].dataSet, 'x00200032', 3); } } return imagePositionPatient; } function extractOrientationFromDataset(dataSet) { let imageOrientationPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet, 'x00200037', 6); if (!imageOrientationPatient && dataSet.elements.x00209116) { imageOrientationPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet.elements.x00209116.items[0].dataSet, 'x00200037', 6); } if (!imageOrientationPatient) { imageOrientationPatient = extractOrientationFromNMMultiframeDataset(dataSet); } return imageOrientationPatient; } function extractPositionFromDataset(dataSet) { let imagePositionPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet, 'x00200032', 3); if (!imagePositionPatient && dataSet.elements.x00209113) { imagePositionPatient = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet.elements.x00209113.items[0].dataSet, 'x00200032', 3); } if (!imagePositionPatient) { imagePositionPatient = extractPositionFromNMMultiframeDataset(dataSet); } return imagePositionPatient; } function extractSpacingFromDataset(dataSet) { let pixelSpacing = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet, 'x00280030', 2); if (!pixelSpacing && dataSet.elements.x00289110) { pixelSpacing = (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_1__["default"])(dataSet.elements.x00289110.items[0].dataSet, 'x00280030', 2); } return pixelSpacing; } function extractSliceThicknessFromDataset(dataSet) { let sliceThickness; if (dataSet.elements.x00180050) { sliceThickness = dataSet.floatString('x00180050'); } else if (dataSet.elements.x00289110 && dataSet.elements.x00289110.items.length > 0 && dataSet.elements.x00289110.items[0].dataSet.elements.x00180050) { sliceThickness = dataSet.elements.x00289110.items[0].dataSet.floatString('x00180050'); } return sliceThickness; } /***/ }, /***/ 33627 /*!*****************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/getImagePixelModule.js ***! \*****************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getLutDescriptor(dataSet, tag) { if (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) { return; } return [dataSet.uint16(tag, 0), dataSet.uint16(tag, 1), dataSet.uint16(tag, 2)]; } function getLutData(lutDataSet, tag, lutDescriptor) { const lut = []; const lutData = lutDataSet.elements[tag]; for (let index = 0; index < lutDescriptor[0]; index++) { lut[index] = lutDescriptor[2] === 16 ? lutDataSet.uint16(tag, index) : lutDataSet.byteArray[index + lutData.dataOffset]; } return lut; } function populatePaletteColorLut(dataSet, imagePixelModule) { imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(dataSet, 'x00281101'); imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(dataSet, 'x00281102'); imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(dataSet, 'x00281103'); if (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) { imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65_536; imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65_536; imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65_536; } const numberLutEntries = imagePixelModule.redPaletteColorLookupTableDescriptor[0]; const lutData = dataSet.elements.x00281201; const lutBitsAllocated = lutData.length === numberLutEntries ? 8 : 16; if (imagePixelModule.redPaletteColorLookupTableDescriptor[2] !== lutBitsAllocated) { imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated; imagePixelModule.greenPaletteColorLookupTableDescriptor[2] = lutBitsAllocated; imagePixelModule.bluePaletteColorLookupTableDescriptor[2] = lutBitsAllocated; } imagePixelModule.redPaletteColorLookupTableData = getLutData(dataSet, 'x00281201', imagePixelModule.redPaletteColorLookupTableDescriptor); imagePixelModule.greenPaletteColorLookupTableData = getLutData(dataSet, 'x00281202', imagePixelModule.greenPaletteColorLookupTableDescriptor); imagePixelModule.bluePaletteColorLookupTableData = getLutData(dataSet, 'x00281203', imagePixelModule.bluePaletteColorLookupTableDescriptor); } function populateSmallestLargestPixelValues(dataSet, imagePixelModule) { const pixelRepresentation = dataSet.uint16('x00280103'); if (pixelRepresentation === 0) { imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106'); imagePixelModule.largestPixelValue = dataSet.uint16('x00280107'); } else { imagePixelModule.smallestPixelValue = dataSet.int16('x00280106'); imagePixelModule.largestPixelValue = dataSet.int16('x00280107'); } } function getImagePixelModule(dataSet) { const imagePixelModule = { samplesPerPixel: dataSet.uint16('x00280002'), photometricInterpretation: dataSet.string('x00280004'), rows: dataSet.uint16('x00280010'), columns: dataSet.uint16('x00280011'), bitsAllocated: dataSet.uint16('x00280100'), bitsStored: dataSet.uint16('x00280101'), highBit: dataSet.uint16('x00280102'), pixelRepresentation: dataSet.uint16('x00280103'), planarConfiguration: dataSet.uint16('x00280006'), pixelAspectRatio: dataSet.string('x00280034') }; populateSmallestLargestPixelValues(dataSet, imagePixelModule); if (imagePixelModule.photometricInterpretation === 'PALETTE COLOR' && dataSet.elements.x00281101) { populatePaletteColorLut(dataSet, imagePixelModule); } return imagePixelModule; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getImagePixelModule); /***/ }, /***/ 13322 /*!*****************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/getLUTs.js ***! \*****************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getLUT(pixelRepresentation, lutDataSet) { let numberLUTEntries = lutDataSet.uint16('x00283002', 0); if (numberLUTEntries === 0) { numberLUTEntries = 65_535; } let firstValueMapped = 0; firstValueMapped = pixelRepresentation === 0 ? lutDataSet.uint16('x00283002', 1) : lutDataSet.int16('x00283002', 1); const numberBitsPerEntry = lutDataSet.uint16('x00283002', 2); const lut = { id: '1', firstValueMapped, numBitsPerEntry: numberBitsPerEntry, lut: [] }; for (let index = 0; index < numberLUTEntries; index++) { lut.lut[index] = pixelRepresentation === 0 ? lutDataSet.uint16('x00283006', index) : lutDataSet.int16('x00283006', index); } return lut; } function getLUTs(pixelRepresentation, lutSequence) { if (!lutSequence || !lutSequence.items || lutSequence.items.length === 0) { return; } const luts = []; for (let index = 0; index < lutSequence.items.length; index++) { const lutDataSet = lutSequence.items[index].dataSet; const lut = getLUT(pixelRepresentation, lutDataSet); if (lut) { luts.push(lut); } } return luts; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getLUTs); /***/ }, /***/ 1974 /*!*************************************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/getModalityLUTOutputPixelRepresentation.js ***! \*************************************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getMinStoredPixelValue(dataSet) { const pixelRepresentation = dataSet.uint16('x00280103'); const bitsStored = dataSet.uint16('x00280101'); if (pixelRepresentation === 0) { return 0; } return -1 << bitsStored - 1; } function getModalityLUTOutputPixelRepresentation(dataSet) { const sopClassUID = dataSet.string('x00080016'); if (sopClassUID === '1.2.840.10008.5.1.4.1.1.2' || sopClassUID === '1.2.840.10008.5.1.4.1.1.2.1') { return 1; } const rescaleIntercept = dataSet.floatString('x00281052'); const rescaleSlope = dataSet.floatString('x00281053'); if (rescaleIntercept !== undefined && rescaleSlope !== undefined) { const minStoredPixelValue = getMinStoredPixelValue(dataSet); const minModalityLutValue = minStoredPixelValue * rescaleSlope + rescaleIntercept; if (minModalityLutValue < 0) { return 1; } return 0; } if (dataSet.elements.x00283000 && dataSet.elements.x00283000.length > 0) { return 0; } return dataSet.uint16('x00280103'); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getModalityLUTOutputPixelRepresentation); /***/ }, /***/ 92939 /*!*************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/getNumberValues.js ***! \*************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getNumberValues(dataSet, tag, minimumLength) { const values = []; const valueAsString = dataSet.string(tag); if (!valueAsString) { return; } const split = valueAsString.split('\\'); if (minimumLength && split.length < minimumLength) { return; } for (const element of split) { values.push(Number.parseFloat(element)); } return values; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getNumberValues); /***/ }, /***/ 5062 /*!*******************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/getOverlayPlaneModule.js ***! \*******************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getOverlayPlaneModule) /* harmony export */ }); function getOverlayPlaneModule(dataSet) { const overlays = []; for (let overlayGroup = 0x00; overlayGroup <= 0x1e; overlayGroup += 0x02) { let groupString = `x60${overlayGroup.toString(16)}`; if (groupString.length === 4) { groupString = `x600${overlayGroup.toString(16)}`; } const data = dataSet.elements[`${groupString}3000`]; if (!data) { continue; } const pixelData = []; for (let index = 0; index < data.length; index++) { for (let k = 0; k < 8; k++) { const byte_as_int = dataSet.byteArray[data.dataOffset + index]; pixelData[index * 8 + k] = byte_as_int >> k & 0b1; } } overlays.push({ rows: dataSet.uint16(`${groupString}0010`), columns: dataSet.uint16(`${groupString}0011`), type: dataSet.string(`${groupString}0040`), x: dataSet.int16(`${groupString}0050`, 1) - 1, y: dataSet.int16(`${groupString}0050`, 0) - 1, pixelData, description: dataSet.string(`${groupString}0022`), label: dataSet.string(`${groupString}1500`), roiArea: dataSet.string(`${groupString}1301`), roiMean: dataSet.string(`${groupString}1302`), roiStandardDeviation: dataSet.string(`${groupString}1303`) }); } return { overlays }; } /***/ }, /***/ 67960 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/index.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getImagePixelModule: () => (/* reexport safe */ _getImagePixelModule__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ getLUTs: () => (/* reexport safe */ _getLUTs__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ getModalityLUTOutputPixelRepresentation: () => (/* reexport safe */ _getModalityLUTOutputPixelRepresentation__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ getNumberValues: () => (/* reexport safe */ _getNumberValues__WEBPACK_IMPORTED_MODULE_3__["default"]), /* harmony export */ metaDataProvider: () => (/* reexport safe */ _metaDataProvider__WEBPACK_IMPORTED_MODULE_4__["default"]), /* harmony export */ metadataForDataset: () => (/* reexport safe */ _metaDataProvider__WEBPACK_IMPORTED_MODULE_4__.metadataForDataset) /* harmony export */ }); /* harmony import */ var _getImagePixelModule__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getImagePixelModule */ 33627); /* harmony import */ var _getLUTs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getLUTs */ 13322); /* harmony import */ var _getModalityLUTOutputPixelRepresentation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./getModalityLUTOutputPixelRepresentation */ 1974); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./getNumberValues */ 92939); /* harmony import */ var _metaDataProvider__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./metaDataProvider */ 68590); /***/ }, /***/ 68590 /*!**************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/metaData/metaDataProvider.js ***! \**************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ metadataForDataset: () => (/* binding */ metadataForDataset) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 67855); /* harmony import */ var dicom_parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! dicom-parser */ 99564); /* harmony import */ var _getInstanceModule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../getInstanceModule */ 20645); /* harmony import */ var _isNMReconstructable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../isNMReconstructable */ 52819); /* harmony import */ var _combineFrameInstanceDataset__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../combineFrameInstanceDataset */ 47719); /* harmony import */ var _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../dataSetCacheManager */ 59201); /* harmony import */ var _parseImageId__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../parseImageId */ 59875); /* harmony import */ var _retrieveMultiframeDataset__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../retrieveMultiframeDataset */ 46526); /* harmony import */ var _extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./extractPositioningFromDataset */ 88346); /* harmony import */ var _getImagePixelModule__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./getImagePixelModule */ 33627); /* harmony import */ var _getLUTs__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./getLUTs */ 13322); /* harmony import */ var _getModalityLUTOutputPixelRepresentation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./getModalityLUTOutputPixelRepresentation */ 1974); /* harmony import */ var _getNumberValues__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./getNumberValues */ 92939); /* harmony import */ var _getOverlayPlaneModule__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./getOverlayPlaneModule */ 5062); /* harmony import */ var _USHelpers__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./USHelpers */ 65977); function metaDataProvider(type, imageId) { const { MetadataModules } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; if (Array.isArray(imageId)) { return; } const parsedImageId = (0,_parseImageId__WEBPACK_IMPORTED_MODULE_6__["default"])(imageId); if (type === MetadataModules.MULTIFRAME) { const multiframeData = _retrieveMultiframeDataset__WEBPACK_IMPORTED_MODULE_7__["default"].retrieveMultiframeDataset(parsedImageId.url); if (!multiframeData.dataSet) { return; } const multiframeInfo = (0,_combineFrameInstanceDataset__WEBPACK_IMPORTED_MODULE_4__.getDirectFrameInformation)(multiframeData.dataSet, multiframeData.frame); return multiframeInfo; } let url = parsedImageId.url; if (parsedImageId.frame) { url = `${url}&frame=${parsedImageId.frame}`; } const dataSet = _dataSetCacheManager__WEBPACK_IMPORTED_MODULE_5__["default"].get(url); if (!dataSet) { return; } return metadataForDataset(type, imageId, dataSet); } function metadataForDataset(type, imageId, dataSet) { const { MetadataModules } = _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__; if (type === MetadataModules.GENERAL_STUDY) { return { studyDescription: dataSet.string('x00081030'), studyDate: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseDA(dataSet.string('x00080020')), studyTime: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseTM(dataSet.string('x00080030') || ''), accessionNumber: dataSet.string('x00080050') }; } if (type === MetadataModules.GENERAL_SERIES) { return { modality: dataSet.string('x00080060'), seriesInstanceUID: dataSet.string('x0020000e'), seriesNumber: dataSet.intString('x00200011'), studyInstanceUID: dataSet.string('x0020000d'), seriesDate: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseDA(dataSet.string('x00080021')), seriesTime: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseTM(dataSet.string('x00080031') || ''), acquisitionDate: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseDA(dataSet.string('x00080022')), acquisitionTime: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseTM(dataSet.string('x00080032') || '') }; } if (type === MetadataModules.GENERAL_IMAGE) { return { sopInstanceUID: dataSet.string('x00080018'), instanceNumber: dataSet.intString('x00200013'), lossyImageCompression: dataSet.string('x00282110'), lossyImageCompressionRatio: dataSet.floatString('x00282112'), lossyImageCompressionMethod: dataSet.string('x00282114') }; } if (type === MetadataModules.PATIENT) { return { patientID: dataSet.string('x00100020'), patientName: dataSet.string('x00100010') }; } if (type === MetadataModules.PATIENT_STUDY) { return { patientAge: dataSet.intString('x00101010'), patientSize: dataSet.floatString('x00101020'), patientSex: dataSet.string('x00100040'), patientWeight: dataSet.floatString('x00101030') }; } if (type === MetadataModules.NM_MULTIFRAME_GEOMETRY) { const modality = dataSet.string('x00080060'); const imageSubType = (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.getImageTypeSubItemFromDataset)(dataSet, 2); return { modality, imageType: dataSet.string('x00080008'), imageSubType, imageOrientationPatient: (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractOrientationFromDataset)(dataSet), imagePositionPatient: (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractPositionFromDataset)(dataSet), sliceThickness: (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractSliceThicknessFromDataset)(dataSet), pixelSpacing: (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractSpacingFromDataset)(dataSet), numberOfFrames: dataSet.uint16('x00280008'), isNMReconstructable: (0,_isNMReconstructable__WEBPACK_IMPORTED_MODULE_3__["default"])(imageSubType) && modality.includes('NM') }; } if (type === MetadataModules.IMAGE_PLANE) { const imageOrientationPatient = (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractOrientationFromDataset)(dataSet); const imagePositionPatient = (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractPositionFromDataset)(dataSet); const pixelSpacing = (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractSpacingFromDataset)(dataSet); const sliceThickness = (0,_extractPositioningFromDataset__WEBPACK_IMPORTED_MODULE_8__.extractSliceThicknessFromDataset)(dataSet); let columnPixelSpacing = null; let rowPixelSpacing = null; if (pixelSpacing) { rowPixelSpacing = pixelSpacing[0]; columnPixelSpacing = pixelSpacing[1]; } let rowCosines = null; let columnCosines = null; if (imageOrientationPatient) { rowCosines = [Number.parseFloat(imageOrientationPatient[0]), Number.parseFloat(imageOrientationPatient[1]), Number.parseFloat(imageOrientationPatient[2])]; columnCosines = [Number.parseFloat(imageOrientationPatient[3]), Number.parseFloat(imageOrientationPatient[4]), Number.parseFloat(imageOrientationPatient[5])]; } return { frameOfReferenceUID: dataSet.string('x00200052'), rows: dataSet.uint16('x00280010'), columns: dataSet.uint16('x00280011'), imageOrientationPatient, rowCosines, columnCosines, imagePositionPatient, sliceThickness, sliceLocation: dataSet.floatString('x00201041'), pixelSpacing, rowPixelSpacing, columnPixelSpacing }; } if (type === MetadataModules.CINE) { return { frameTime: dataSet.floatString('x00181063') }; } if (type === MetadataModules.IMAGE_PIXEL) { return (0,_getImagePixelModule__WEBPACK_IMPORTED_MODULE_9__["default"])(dataSet); } if (type === MetadataModules.VOI_LUT) { const modalityLUTOutputPixelRepresentation = (0,_getModalityLUTOutputPixelRepresentation__WEBPACK_IMPORTED_MODULE_11__["default"])(dataSet); return { windowCenter: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_12__["default"])(dataSet, 'x00281050', 1), windowWidth: (0,_getNumberValues__WEBPACK_IMPORTED_MODULE_12__["default"])(dataSet, 'x00281051', 1), voiLUTSequence: (0,_getLUTs__WEBPACK_IMPORTED_MODULE_10__["default"])(modalityLUTOutputPixelRepresentation, dataSet.elements.x00283010), voiLUTFunction: dataSet.string('x00281056') }; } if (type === MetadataModules.MODALITY_LUT) { return { rescaleIntercept: dataSet.floatString('x00281052'), rescaleSlope: dataSet.floatString('x00281053'), rescaleType: dataSet.string('x00281054'), modalityLUTSequence: (0,_getLUTs__WEBPACK_IMPORTED_MODULE_10__["default"])(dataSet.uint16('x00280103'), dataSet.elements.x00283000) }; } if (type === MetadataModules.SOP_COMMON) { return { sopClassUID: dataSet.string('x00080016'), sopInstanceUID: dataSet.string('x00080018') }; } if (type === MetadataModules.PET_ISOTOPE) { const radiopharmaceuticalInfo = dataSet.elements.x00540016; if (radiopharmaceuticalInfo === undefined) { return; } const firstRadiopharmaceuticalInfoDataSet = radiopharmaceuticalInfo.items[0].dataSet; return { radiopharmaceuticalInfo: { radiopharmaceuticalStartTime: dicom_parser__WEBPACK_IMPORTED_MODULE_1__.parseTM(firstRadiopharmaceuticalInfoDataSet.string('x00181072') || ''), radionuclideTotalDose: firstRadiopharmaceuticalInfoDataSet.floatString('x00181074'), radionuclideHalfLife: firstRadiopharmaceuticalInfoDataSet.floatString('x00181075') } }; } if (type === MetadataModules.OVERLAY_PLANE) { return (0,_getOverlayPlaneModule__WEBPACK_IMPORTED_MODULE_13__["default"])(dataSet); } if (type === 'transferSyntax') { let transferSyntaxUID; try { transferSyntaxUID = dataSet.string('x00020010'); } catch {} return { transferSyntaxUID }; } if (type === MetadataModules.PET_SERIES) { return { correctedImage: dataSet.string('x00280051'), units: dataSet.string('x00541001'), decayCorrection: dataSet.string('x00541102') }; } if (type === MetadataModules.PET_IMAGE) { return { frameReferenceTime: dataSet.floatString(dataSet.string('x00541300') || ''), actualFrameDuration: dataSet.intString(dataSet.string('x00181242')) }; } if (type === MetadataModules.ULTRASOUND_ENHANCED_REGION) { return (0,_USHelpers__WEBPACK_IMPORTED_MODULE_14__.getUSEnhancedRegions)(dataSet); } if (type === MetadataModules.CALIBRATION) { const modality = dataSet.string('x00080060'); if (modality === 'US') { const enhancedRegion = (0,_USHelpers__WEBPACK_IMPORTED_MODULE_14__.getUSEnhancedRegions)(dataSet); return { sequenceOfUltrasoundRegions: enhancedRegion }; } } if (type === 'instance') { return (0,_getInstanceModule__WEBPACK_IMPORTED_MODULE_2__.getInstanceModule)(imageId, metaDataProvider, _getInstanceModule__WEBPACK_IMPORTED_MODULE_2__.instanceModuleNames); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (metaDataProvider); /***/ }, /***/ 59875 /*!*************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/parseImageId.js ***! \*************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function parseImageId(imageId) { const firstColonIndex = imageId.indexOf(':'); let url = imageId.slice(Math.max(0, firstColonIndex + 1)); const frameIndex = url.indexOf('frame='); let frame; if (frameIndex !== -1) { const frameString = url.slice(Math.max(0, frameIndex + 6)); frame = Number.parseInt(frameString, 10); url = url.slice(0, Math.max(0, frameIndex - 1)); } const scheme = imageId.slice(0, Math.max(0, firstColonIndex)); const adjustedFrame = frame === undefined ? undefined : frame - 1; return { scheme, url, frame, pixelDataFrame: adjustedFrame }; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (parseImageId); /***/ }, /***/ 19095 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/register.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @cornerstonejs/core */ 90161); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/core */ 96035); /* harmony import */ var _loadImage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./loadImage */ 73321); /* harmony import */ var _metaData_index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./metaData/index */ 67960); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__() { (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.registerImageLoader)('dicomweb', _loadImage__WEBPACK_IMPORTED_MODULE_2__.loadImage); (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.registerImageLoader)('wadouri', _loadImage__WEBPACK_IMPORTED_MODULE_2__.loadImage); (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_1__.registerImageLoader)('dicomfile', _loadImage__WEBPACK_IMPORTED_MODULE_2__.loadImage); _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__.addProvider(_metaData_index__WEBPACK_IMPORTED_MODULE_3__.metaDataProvider); } /***/ }, /***/ 46526 /*!**************************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/retrieveMultiframeDataset.js ***! \**************************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _loadedDataSets__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./loadedDataSets */ 30826); function _get(uri) { if (!_loadedDataSets__WEBPACK_IMPORTED_MODULE_0__.loadedDataSets[uri]) { return; } return _loadedDataSets__WEBPACK_IMPORTED_MODULE_0__.loadedDataSets[uri]; } function isMultiframeDataset(uri) { const dataSet = _get(uri); return _isMultiframeDataset(dataSet); } function _isMultiframeDataset(dataSet) { if (!dataSet) { return false; } const numberOfFrames = dataSet.intString('x00280008'); return numberOfFrames && numberOfFrames > 1; } function retrieveFrameParameterIndex(uri) { return uri.indexOf('&frame='); } function retrieveMultiframeDataset(uri) { const frameParameterIndex = retrieveFrameParameterIndex(uri); const multiframeURI = frameParameterIndex === -1 ? uri : uri.slice(0, frameParameterIndex); const frame = Number.parseInt(uri.slice(frameParameterIndex + 7), 10) || 1; let dataSet; dataSet = _loadedDataSets__WEBPACK_IMPORTED_MODULE_0__.loadedDataSets[multiframeURI] ? _loadedDataSets__WEBPACK_IMPORTED_MODULE_0__.loadedDataSets[multiframeURI].dataSet : undefined; return { dataSet, frame }; } function generateMultiframeWADOURIs(uri) { const listWADOURIs = []; const dataSet = _get(uri); if (_isMultiframeDataset(dataSet)) { const numberOfFrames = dataSet.intString('x00280008'); for (let index = 1; index <= numberOfFrames; index++) { listWADOURIs.push(`${uri}&frame=${index}`); } } else { listWADOURIs.push(uri); } return listWADOURIs; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ _get, generateMultiframeWADOURIs, retrieveMultiframeDataset, isMultiframeDataset }); /***/ }, /***/ 57612 /*!******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/imageLoader/wadouri/unpackBinaryFrame.js ***! \******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function isBitSet(byte, bitPos) { return byte & 1 << bitPos; } function unpackBinaryFrame(byteArray, frameOffset, pixelsPerFrame) { const pixelData = new Uint8Array(pixelsPerFrame); for (let index = 0; index < pixelsPerFrame; index++) { const bytePos = Math.floor(index / 8); const byte = byteArray[bytePos + frameOffset]; const bitPos = index % 8; pixelData[index] = isBitSet(byte, bitPos) ? 1 : 0; } return pixelData; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (unpackBinaryFrame); /***/ }, /***/ 99763 /*!**********************************************!*\ !*** ./libs/dicom-image-loader-dev/index.js ***! \**********************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ constants: () => (/* reexport module object */ _constants__WEBPACK_IMPORTED_MODULE_0__), /* harmony export */ convertColorSpace: () => (/* reexport safe */ _imageLoader_convertColorSpace__WEBPACK_IMPORTED_MODULE_3__["default"]), /* harmony export */ convertPALETTECOLOR: () => (/* reexport safe */ _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertPALETTECOLOR), /* harmony export */ convertRGBColorByPixel: () => (/* reexport safe */ _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertRGBColorByPixel), /* harmony export */ convertRGBColorByPlane: () => (/* reexport safe */ _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertRGBColorByPlane), /* harmony export */ convertYBRFullByPixel: () => (/* reexport safe */ _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertYBRFullByPixel), /* harmony export */ convertYBRFullByPlane: () => (/* reexport safe */ _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertYBRFullByPlane), /* harmony export */ createImage: () => (/* reexport safe */ _imageLoader_createImage__WEBPACK_IMPORTED_MODULE_4__["default"]), /* harmony export */ decodeImageFrame: () => (/* reexport safe */ _decodeImageFrameWorker__WEBPACK_IMPORTED_MODULE_1__.decodeImageFrame), /* harmony export */ decodeJPEGBaseline8BitColor: () => (/* reexport safe */ _imageLoader_decodeJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_5__["default"]), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ getImageFrame: () => (/* reexport safe */ _imageLoader_getImageFrame__WEBPACK_IMPORTED_MODULE_6__["default"]), /* harmony export */ getMinMax: () => (/* reexport safe */ _shared_getMinMax__WEBPACK_IMPORTED_MODULE_13__["default"]), /* harmony export */ getPixelData: () => (/* reexport safe */ _imageLoader_wadors_getPixelData__WEBPACK_IMPORTED_MODULE_9__["default"]), /* harmony export */ init: () => (/* reexport safe */ _init__WEBPACK_IMPORTED_MODULE_12__["default"]), /* harmony export */ internal: () => (/* reexport safe */ _imageLoader_internal_index__WEBPACK_IMPORTED_MODULE_7__.internal), /* harmony export */ isColorImage: () => (/* reexport safe */ _shared_isColorImage__WEBPACK_IMPORTED_MODULE_14__["default"]), /* harmony export */ isJPEGBaseline8BitColor: () => (/* reexport safe */ _imageLoader_isJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_8__["default"]), /* harmony export */ wadors: () => (/* reexport safe */ _imageLoader_wadors_index__WEBPACK_IMPORTED_MODULE_10__["default"]), /* harmony export */ wadouri: () => (/* reexport safe */ _imageLoader_wadouri_index__WEBPACK_IMPORTED_MODULE_11__["default"]) /* harmony export */ }); /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ 25189); /* harmony import */ var _decodeImageFrameWorker__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./decodeImageFrameWorker */ 68149); /* harmony import */ var _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./imageLoader/colorSpaceConverters/index */ 62109); /* harmony import */ var _imageLoader_convertColorSpace__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./imageLoader/convertColorSpace */ 28110); /* harmony import */ var _imageLoader_createImage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./imageLoader/createImage */ 22555); /* harmony import */ var _imageLoader_decodeJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./imageLoader/decodeJPEGBaseline8BitColor */ 78669); /* harmony import */ var _imageLoader_getImageFrame__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./imageLoader/getImageFrame */ 56076); /* harmony import */ var _imageLoader_internal_index__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./imageLoader/internal/index */ 52610); /* harmony import */ var _imageLoader_isJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./imageLoader/isJPEGBaseline8BitColor */ 23543); /* harmony import */ var _imageLoader_wadors_getPixelData__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./imageLoader/wadors/getPixelData */ 61185); /* harmony import */ var _imageLoader_wadors_index__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./imageLoader/wadors/index */ 83973); /* harmony import */ var _imageLoader_wadouri_index__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./imageLoader/wadouri/index */ 67816); /* harmony import */ var _init__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./init */ 15781); /* harmony import */ var _shared_getMinMax__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./shared/getMinMax */ 67151); /* harmony import */ var _shared_isColorImage__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./shared/isColorImage */ 93109); const cornerstoneDICOMImageLoader = { constants: _constants__WEBPACK_IMPORTED_MODULE_0__, convertRGBColorByPixel: _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertRGBColorByPixel, convertRGBColorByPlane: _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertRGBColorByPlane, convertYBRFullByPixel: _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertYBRFullByPixel, convertYBRFullByPlane: _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertYBRFullByPlane, convertPALETTECOLOR: _imageLoader_colorSpaceConverters_index__WEBPACK_IMPORTED_MODULE_2__.convertPALETTECOLOR, wadouri: _imageLoader_wadouri_index__WEBPACK_IMPORTED_MODULE_11__["default"], wadors: _imageLoader_wadors_index__WEBPACK_IMPORTED_MODULE_10__["default"], init: _init__WEBPACK_IMPORTED_MODULE_12__["default"], convertColorSpace: _imageLoader_convertColorSpace__WEBPACK_IMPORTED_MODULE_3__["default"], createImage: _imageLoader_createImage__WEBPACK_IMPORTED_MODULE_4__["default"], decodeJPEGBaseline8BitColor: _imageLoader_decodeJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_5__["default"], getImageFrame: _imageLoader_getImageFrame__WEBPACK_IMPORTED_MODULE_6__["default"], getPixelData: _imageLoader_wadors_getPixelData__WEBPACK_IMPORTED_MODULE_9__["default"], getMinMax: _shared_getMinMax__WEBPACK_IMPORTED_MODULE_13__["default"], isColorImage: _shared_isColorImage__WEBPACK_IMPORTED_MODULE_14__["default"], isJPEGBaseline8BitColor: _imageLoader_isJPEGBaseline8BitColor__WEBPACK_IMPORTED_MODULE_8__["default"], internal: _imageLoader_internal_index__WEBPACK_IMPORTED_MODULE_7__.internal, decodeImageFrame: _decodeImageFrameWorker__WEBPACK_IMPORTED_MODULE_1__.decodeImageFrame }; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (cornerstoneDICOMImageLoader); /***/ }, /***/ 15781 /*!*********************************************!*\ !*** ./libs/dicom-image-loader-dev/init.js ***! \*********************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _imageLoader_internal_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./imageLoader/internal/index */ 52610); /* harmony import */ var _imageLoader_registerLoaders__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./imageLoader/registerLoaders */ 65173); /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @cornerstonejs/core */ 15678); const workerFunction = () => { const instance = new Worker(__webpack_require__.tu(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(0), __webpack_require__.b)), { type: undefined }); return instance; }; // Module-level flag to ensure the web worker is only registered once even if // `init()` is called multiple times across the app. let _workerRegistered = false; function init(options = {}) { (0,_imageLoader_internal_index__WEBPACK_IMPORTED_MODULE_0__.setOptions)(options); (0,_imageLoader_registerLoaders__WEBPACK_IMPORTED_MODULE_1__["default"])(); const isValidWorkerFactory = validateWorkerFactoryOption(options); const workerManager = (0,_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_2__.getWebWorkerManager)(); const maxWorkers = options?.maxWebWorkers || getReasonableWorkerCount(); // Only register the worker once. If registration was already done in // another part of the app, skip re-registering to avoid the warning. if (!_workerRegistered) { try { workerManager.registerWorker('dicomImageLoader', isValidWorkerFactory ? options.webWorkerFactory : workerFunction, { maxWorkerInstances: maxWorkers }); _workerRegistered = true; } catch { // Some implementations of the worker manager may throw when trying // to re-register the same worker type. Ignore that and continue. // Still set the flag to avoid repeated attempts. _workerRegistered = true; } } } function getReasonableWorkerCount() { if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) { return Math.max(1, Math.floor(navigator.hardwareConcurrency / 2)); } return 1; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (init); function validateWorkerFactoryOption(options) { const isValidWorkerFactory = options.webWorkerFactory && typeof options.webWorkerFactory === 'function'; if (!!options.webWorkerFactory && !isValidWorkerFactory) { console.warn('webWorkerFactory should be a function that returns a Worker instance.'); } return isValidWorkerFactory; } /***/ }, /***/ 14148 /*!************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeBigEndian.js ***! \************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); function swap16(value) { return (value & 0xff) << 8 | value >> 8 & 0xff; } function decodeBigEndian(_x, _x2) { return _decodeBigEndian.apply(this, arguments); } function _decodeBigEndian() { _decodeBigEndian = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, pixelData) { if (imageFrame.bitsAllocated === 16) { let arrayBuffer = pixelData.buffer; let offset = pixelData.byteOffset; const length = pixelData.length; if (offset % 2) { arrayBuffer = arrayBuffer.slice(offset); offset = 0; } imageFrame.pixelData = imageFrame.pixelRepresentation === 0 ? new Uint16Array(arrayBuffer, offset, length / 2) : new Int16Array(arrayBuffer, offset, length / 2); for (let index = 0; index < imageFrame.pixelData.length; index++) { imageFrame.pixelData[index] = swap16(imageFrame.pixelData[index]); } } else if (imageFrame.bitsAllocated === 8) { imageFrame.pixelData = pixelData; } return imageFrame; }); return _decodeBigEndian.apply(this, arguments); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeBigEndian); /***/ }, /***/ 61368 /*!********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeHTJ2K.js ***! \********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ initialize: () => (/* binding */ initialize) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_codec_openjph_wasmjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/codec-openjph/wasmjs */ 18521); const openjphWasm = new URL('@cornerstonejs/codec-openjph/wasm', "file:///Users/jakewalsh/Documents/projects/tomoverse/tvct-clinical/libs/dicom-image-loader-dev/shared/decoders/decodeHTJ2K.js"); const local = { codec: undefined, decoder: undefined, decodeConfig: {} }; function calculateSizeAtDecompositionLevel(decompositionLevel, frameWidth, frameHeight) { const result = { width: frameWidth, height: frameHeight }; while (decompositionLevel > 0) { result.width = Math.ceil(result.width / 2); result.height = Math.ceil(result.height / 2); decompositionLevel--; } return result; } function initialize(decodeConfig, wasmUrlCodecOpenJph) { local.decodeConfig = decodeConfig; if (local.codec) { return Promise.resolve(); } const openJphModule = _cornerstonejs_codec_openjph_wasmjs__WEBPACK_IMPORTED_MODULE_1__({ locateFile: f => { if (f.endsWith('.wasm')) { if (wasmUrlCodecOpenJph) { return wasmUrlCodecOpenJph; } return openjphWasm.toString(); } return f; } }); return new Promise((resolve, reject) => { openJphModule.then(instance => { local.codec = instance; local.decoder = new instance.HTJ2KDecoder(); resolve(); }, reject); }); } function decodeAsync(_x, _x2, _x3) { return _decodeAsync.apply(this, arguments); } function _decodeAsync() { _decodeAsync = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (compressedImageFrame, imageInfo, wasmUrlCodecOpenJph) { yield initialize(undefined, wasmUrlCodecOpenJph); const decoder = new local.codec.HTJ2KDecoder(); const encodedBufferInWASM = decoder.getEncodedBuffer(compressedImageFrame.length); encodedBufferInWASM.set(compressedImageFrame); const decodeLevel = imageInfo.decodeLevel || 0; decoder.decodeSubResolution(decodeLevel); const frameInfo = decoder.getFrameInfo(); if (imageInfo.decodeLevel > 0) { const { width, height } = calculateSizeAtDecompositionLevel(imageInfo.decodeLevel, frameInfo.width, frameInfo.height); frameInfo.width = width; frameInfo.height = height; } const decodedBufferInWASM = decoder.getDecodedBuffer(); const imageFrame = new Uint8Array(decodedBufferInWASM.length); imageFrame.set(decodedBufferInWASM); const imageOffset = `x: ${decoder.getImageOffset().x}, y: ${decoder.getImageOffset().y}`; const numberDecompositions = decoder.getNumDecompositions(); const numberLayers = decoder.getNumLayers(); const progessionOrder = ['unknown', 'LRCP', 'RLCP', 'RPCL', 'PCRL', 'CPRL'][decoder.getProgressionOrder() + 1]; const reversible = decoder.getIsReversible(); const blockDimensions = `${decoder.getBlockDimensions().width} x ${decoder.getBlockDimensions().height}`; const tileSize = `${decoder.getTileSize().width} x ${decoder.getTileSize().height}`; const tileOffset = `${decoder.getTileOffset().x}, ${decoder.getTileOffset().y}`; const decodedSize = `${decodedBufferInWASM.length.toLocaleString()} bytes`; const compressionRatio = `${(decodedBufferInWASM.length / encodedBufferInWASM.length).toFixed(2)}:1`; const encodedImageInfo = { columns: frameInfo.width, rows: frameInfo.height, bitsPerPixel: frameInfo.bitsPerSample, signed: frameInfo.isSigned, bytesPerPixel: imageInfo.bytesPerPixel, componentsPerPixel: frameInfo.componentCount }; let pixelData = getPixelData(frameInfo, decodedBufferInWASM); const { buffer: b, byteOffset, byteLength } = pixelData; const pixelDataArrayBuffer = b.slice(byteOffset, byteOffset + byteLength); pixelData = new pixelData.constructor(pixelDataArrayBuffer); const encodeOptions = { imageOffset, numDecompositions: numberDecompositions, numLayers: numberLayers, progessionOrder, reversible, blockDimensions, tileSize, tileOffset, decodedSize, compressionRatio }; return { ...imageInfo, pixelData, imageInfo: encodedImageInfo, encodeOptions, ...encodeOptions, ...encodedImageInfo }; }); return _decodeAsync.apply(this, arguments); } function getPixelData(frameInfo, decodedBuffer) { if (frameInfo.bitsPerSample > 8) { if (frameInfo.isSigned) { return new Int16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } return new Uint16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } if (frameInfo.isSigned) { return new Int8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } return new Uint8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeAsync); /***/ }, /***/ 47061 /*!***********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeJPEG2000.js ***! \***********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ initialize: () => (/* binding */ initialize) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_codec_openjpeg_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/codec-openjpeg/decodewasmjs */ 57595); const openjpegWasm = new URL('@cornerstonejs/codec-openjpeg/decodewasm', "file:///Users/jakewalsh/Documents/projects/tomoverse/tvct-clinical/libs/dicom-image-loader-dev/shared/decoders/decodeJPEG2000.js"); const local = { codec: undefined, decoder: undefined, decodeConfig: {} }; function initialize(decodeConfig, wasmUrlCodecOpenJpeg) { local.decodeConfig = decodeConfig; if (local.codec) { return Promise.resolve(); } const openJpegModule = _cornerstonejs_codec_openjpeg_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__({ locateFile: f => { if (f.endsWith('.wasm')) { if (wasmUrlCodecOpenJpeg) { return wasmUrlCodecOpenJpeg; } return openjpegWasm.toString(); } return f; } }); return new Promise((resolve, reject) => { openJpegModule.then(instance => { local.codec = instance; local.decoder = new instance.J2KDecoder(); resolve(); }, reject); }); } function decodeAsync(_x, _x2, _x3) { return _decodeAsync.apply(this, arguments); } function _decodeAsync() { _decodeAsync = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (compressedImageFrame, imageInfo, wasmUrlCodecOpenJpeg) { yield initialize(undefined, wasmUrlCodecOpenJpeg); const decoder = local.decoder; const encodedBufferInWASM = decoder.getEncodedBuffer(compressedImageFrame.length); encodedBufferInWASM.set(compressedImageFrame); decoder.decode(); const frameInfo = decoder.getFrameInfo(); const decodedBufferInWASM = decoder.getDecodedBuffer(); const imageFrame = new Uint8Array(decodedBufferInWASM.length); imageFrame.set(decodedBufferInWASM); const imageOffset = `x: ${decoder.getImageOffset().x}, y: ${decoder.getImageOffset().y}`; const numberDecompositions = decoder.getNumDecompositions(); const numberLayers = decoder.getNumLayers(); const progessionOrder = ['unknown', 'LRCP', 'RLCP', 'RPCL', 'PCRL', 'CPRL'][decoder.getProgressionOrder() + 1]; const reversible = decoder.getIsReversible(); const blockDimensions = `${decoder.getBlockDimensions().width} x ${decoder.getBlockDimensions().height}`; const tileSize = `${decoder.getTileSize().width} x ${decoder.getTileSize().height}`; const tileOffset = `${decoder.getTileOffset().x}, ${decoder.getTileOffset().y}`; const colorTransform = decoder.getColorSpace(); const decodedSize = `${decodedBufferInWASM.length.toLocaleString()} bytes`; const compressionRatio = `${(decodedBufferInWASM.length / encodedBufferInWASM.length).toFixed(2)}:1`; const encodedImageInfo = { columns: frameInfo.width, rows: frameInfo.height, bitsPerPixel: frameInfo.bitsPerSample, signed: frameInfo.isSigned, bytesPerPixel: imageInfo.bytesPerPixel, componentsPerPixel: frameInfo.componentCount }; const pixelData = getPixelData(frameInfo, decodedBufferInWASM); const encodeOptions = { imageOffset, numDecompositions: numberDecompositions, numLayers: numberLayers, progessionOrder, reversible, blockDimensions, tileSize, tileOffset, colorTransform, decodedSize, compressionRatio }; return { ...imageInfo, pixelData, imageInfo: encodedImageInfo, encodeOptions, ...encodeOptions, ...encodedImageInfo }; }); return _decodeAsync.apply(this, arguments); } function getPixelData(frameInfo, decodedBuffer) { if (frameInfo.bitsPerSample > 8) { if (frameInfo.isSigned) { return new Int16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } return new Uint16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } if (frameInfo.isSigned) { return new Int8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } return new Uint8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeAsync); /***/ }, /***/ 38314 /*!***********************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeJPEGBaseline12Bit-js.js ***! \***********************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ initialize: () => (/* binding */ initialize) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); const local = { JpegImage: undefined, decodeConfig: {} }; function initialize(decodeConfig) { local.decodeConfig = decodeConfig; if (local.JpegImage) { return Promise.resolve(); } return new Promise((resolve, reject) => { __webpack_require__.e(/*! import() */ "libs_dicom-image-loader-dev_codecs_jpeg_js").then(__webpack_require__.bind(__webpack_require__, /*! ../../codecs/jpeg */ 53741)).then(module => { local.JpegImage = module.default; resolve(); }).catch(reject); }); } function decodeJPEGBaseline12BitAsync(_x, _x2) { return _decodeJPEGBaseline12BitAsync.apply(this, arguments); } function _decodeJPEGBaseline12BitAsync() { _decodeJPEGBaseline12BitAsync = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, pixelData) { yield initialize(); if (local.JpegImage === undefined) { throw new TypeError('No JPEG Baseline decoder loaded'); } const jpeg = new local.JpegImage(); jpeg.parse(pixelData); jpeg.colorTransform = false; if (imageFrame.bitsAllocated === 8) { imageFrame.pixelData = jpeg.getData(imageFrame.columns, imageFrame.rows); return imageFrame; } else if (imageFrame.bitsAllocated === 16) { imageFrame.pixelData = jpeg.getData16(imageFrame.columns, imageFrame.rows); return imageFrame; } }); return _decodeJPEGBaseline12BitAsync.apply(this, arguments); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeJPEGBaseline12BitAsync); /***/ }, /***/ 94351 /*!*******************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeJPEGBaseline8Bit.js ***! \*******************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_codec_libjpeg_turbo_8bit_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/codec-libjpeg-turbo-8bit/decodewasmjs */ 21674); const libjpegTurboWasm = new URL('@cornerstonejs/codec-libjpeg-turbo-8bit/decodewasm', "file:///Users/jakewalsh/Documents/projects/tomoverse/tvct-clinical/libs/dicom-image-loader-dev/shared/decoders/decodeJPEGBaseline8Bit.js"); const local = { codec: undefined, decoder: undefined }; function initLibjpegTurbo(wasmUrlCodecLibjpegTurbo8bit) { if (local.codec) { return Promise.resolve(); } const libjpegTurboModule = _cornerstonejs_codec_libjpeg_turbo_8bit_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__({ locateFile: f => { if (f.endsWith('.wasm')) { if (wasmUrlCodecLibjpegTurbo8bit) { return wasmUrlCodecLibjpegTurbo8bit; } return libjpegTurboWasm.toString(); } return f; } }); return new Promise((resolve, reject) => { libjpegTurboModule.then(instance => { local.codec = instance; local.decoder = new instance.JPEGDecoder(); resolve(); }, reject); }); } function decodeAsync(_x, _x2, _x3) { return _decodeAsync.apply(this, arguments); } function _decodeAsync() { _decodeAsync = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (compressedImageFrame, imageInfo, wasmUrlCodecLibjpegTurbo8bit) { yield initLibjpegTurbo(wasmUrlCodecLibjpegTurbo8bit); const decoder = local.decoder; const encodedBufferInWASM = decoder.getEncodedBuffer(compressedImageFrame.length); encodedBufferInWASM.set(compressedImageFrame); decoder.decode(); const frameInfo = decoder.getFrameInfo(); const decodedPixelsInWASM = decoder.getDecodedBuffer(); const encodedImageInfo = { columns: frameInfo.width, rows: frameInfo.height, bitsPerPixel: frameInfo.bitsPerSample, signed: imageInfo.signed, bytesPerPixel: imageInfo.bytesPerPixel, componentsPerPixel: frameInfo.componentCount }; const pixelData = getPixelData(frameInfo, decodedPixelsInWASM); const encodeOptions = { frameInfo }; return { ...imageInfo, pixelData, imageInfo: encodedImageInfo, encodeOptions, ...encodeOptions, ...encodedImageInfo }; }); return _decodeAsync.apply(this, arguments); } function getPixelData(frameInfo, decodedBuffer) { if (frameInfo.isSigned) { return new Int8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } return new Uint8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeAsync); /***/ }, /***/ 54782 /*!*********************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeJPEGLS.js ***! \*********************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ initialize: () => (/* binding */ initialize) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); /* harmony import */ var _cornerstonejs_codec_charls_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @cornerstonejs/codec-charls/decodewasmjs */ 41691); const charlsWasm = new URL('@cornerstonejs/codec-charls/decodewasm', "file:///Users/jakewalsh/Documents/projects/tomoverse/tvct-clinical/libs/dicom-image-loader-dev/shared/decoders/decodeJPEGLS.js"); const local = { codec: undefined, decoder: undefined, decodeConfig: {} }; function getExceptionMessage(exception) { return typeof exception === 'number' ? local.codec.getExceptionMessage(exception) : exception; } function initialize(decodeConfig, wasmUrlCodecCharls) { local.decodeConfig = decodeConfig; if (local.codec) { return Promise.resolve(); } const charlsModule = _cornerstonejs_codec_charls_decodewasmjs__WEBPACK_IMPORTED_MODULE_1__({ locateFile: f => { if (f.endsWith('.wasm')) { if (wasmUrlCodecCharls) { return wasmUrlCodecCharls; } return charlsWasm.toString(); } return f; } }); return new Promise((resolve, reject) => { charlsModule.then(instance => { local.codec = instance; local.decoder = new instance.JpegLSDecoder(); resolve(); }, reject); }); } function decodeAsync(_x, _x2, _x3) { return _decodeAsync.apply(this, arguments); } function _decodeAsync() { _decodeAsync = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (compressedImageFrame, imageInfo, wasmUrlCodecCharls) { try { yield initialize(undefined, wasmUrlCodecCharls); const decoder = local.decoder; const encodedBufferInWASM = decoder.getEncodedBuffer(compressedImageFrame.length); encodedBufferInWASM.set(compressedImageFrame); decoder.decode(); const frameInfo = decoder.getFrameInfo(); const interleaveMode = decoder.getInterleaveMode(); const nearLossless = decoder.getNearLossless(); const decodedPixelsInWASM = decoder.getDecodedBuffer(); const encodedImageInfo = { columns: frameInfo.width, rows: frameInfo.height, bitsPerPixel: frameInfo.bitsPerSample, signed: imageInfo.signed, bytesPerPixel: imageInfo.bytesPerPixel, componentsPerPixel: frameInfo.componentCount }; const pixelData = getPixelData(frameInfo, decodedPixelsInWASM, imageInfo.signed); const encodeOptions = { nearLossless, interleaveMode, frameInfo }; return { ...imageInfo, pixelData, imageInfo: encodedImageInfo, encodeOptions, ...encodeOptions, ...encodedImageInfo }; } catch (error) { throw getExceptionMessage(error); } }); return _decodeAsync.apply(this, arguments); } function getPixelData(frameInfo, decodedBuffer, signed) { if (frameInfo.bitsPerSample > 8) { if (signed) { return new Int16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } return new Uint16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } if (signed) { return new Int8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } return new Uint8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeAsync); /***/ }, /***/ 92677 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeJPEGLossless.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ initialize: () => (/* binding */ initialize) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); const local = { jpeg: undefined, decodeConfig: {} }; function initialize(decodeConfig) { local.decodeConfig = decodeConfig; if (local.jpeg) { return Promise.resolve(); } return new Promise((resolve, reject) => { __webpack_require__.e(/*! import() */ "node_modules_jpeg-lossless-decoder-js_release_lossless_js").then(__webpack_require__.bind(__webpack_require__, /*! jpeg-lossless-decoder-js */ 87005)).then(({ Decoder }) => { const decoder = new Decoder(); local.jpeg = decoder; resolve(); }, reject); }); } function decodeJPEGLossless(_x, _x2) { return _decodeJPEGLossless.apply(this, arguments); } function _decodeJPEGLossless() { _decodeJPEGLossless = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, pixelData) { yield initialize(); if (local.jpeg === undefined) { throw new TypeError('No JPEG Lossless decoder loaded'); } const byteOutput = imageFrame.bitsAllocated <= 8 ? 1 : 2; const buffer = pixelData.buffer; const decompressedData = local.jpeg.decode(buffer, pixelData.byteOffset, pixelData.length, byteOutput); if (imageFrame.pixelRepresentation === 0) { if (imageFrame.bitsAllocated === 16) { imageFrame.pixelData = new Uint16Array(decompressedData.buffer); return imageFrame; } imageFrame.pixelData = new Uint8Array(decompressedData.buffer); return imageFrame; } imageFrame.pixelData = new Int16Array(decompressedData.buffer); return imageFrame; }); return _decodeJPEGLossless.apply(this, arguments); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeJPEGLossless); /***/ }, /***/ 31618 /*!***************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeLittleEndian.js ***! \***************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); function decodeLittleEndian(_x, _x2) { return _decodeLittleEndian.apply(this, arguments); } function _decodeLittleEndian() { _decodeLittleEndian = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, pixelData) { let arrayBuffer = pixelData.buffer; let offset = pixelData.byteOffset; const length = pixelData.length; switch (imageFrame.bitsAllocated) { case 1: case 8: { imageFrame.pixelData = pixelData; break; } case 16: { if (offset % 2) { arrayBuffer = arrayBuffer.slice(offset); offset = 0; } imageFrame.pixelData = imageFrame.pixelRepresentation === 0 ? new Uint16Array(arrayBuffer, offset, length / 2) : new Int16Array(arrayBuffer, offset, length / 2); break; } case 32: { if (offset % 2) { arrayBuffer = arrayBuffer.slice(offset); offset = 0; } imageFrame.pixelData = new Float32Array(arrayBuffer, offset, length / 4); break; } // No default } return imageFrame; }); return _decodeLittleEndian.apply(this, arguments); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeLittleEndian); /***/ }, /***/ 60144 /*!******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/decoders/decodeRLE.js ***! \******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@angular-builders/custom-webpack/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 74349); function decodeRLE(_x, _x2) { return _decodeRLE.apply(this, arguments); } function _decodeRLE() { _decodeRLE = (0,_Users_jakewalsh_Documents_projects_tomoverse_tvct_clinical_node_modules_angular_builders_custom_webpack_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (imageFrame, pixelData) { if (imageFrame.bitsAllocated === 8) { if (imageFrame.planarConfiguration) { return decode8Planar(imageFrame, pixelData); } return decode8(imageFrame, pixelData); } else if (imageFrame.bitsAllocated === 16) { return decode16(imageFrame, pixelData); } throw new Error('unsupported pixel format for RLE'); }); return _decodeRLE.apply(this, arguments); } function decode8(imageFrame, pixelData) { const frameData = pixelData; const frameSize = imageFrame.rows * imageFrame.columns; const outFrame = new ArrayBuffer(frameSize * imageFrame.samplesPerPixel); const header = new DataView(frameData.buffer, frameData.byteOffset); const data = new Int8Array(frameData.buffer, frameData.byteOffset); const out = new Int8Array(outFrame); let outIndex = 0; const numberSegments = header.getInt32(0, true); for (let s = 0; s < numberSegments; ++s) { outIndex = s; let inIndex = header.getInt32((s + 1) * 4, true); let maxIndex = header.getInt32((s + 2) * 4, true); if (maxIndex === 0) { maxIndex = frameData.length; } const endOfSegment = frameSize * numberSegments; while (inIndex < maxIndex) { const n = data[inIndex++]; if (n >= 0 && n <= 127) { for (let index = 0; index < n + 1 && outIndex < endOfSegment; ++index) { out[outIndex] = data[inIndex++]; outIndex += imageFrame.samplesPerPixel; } } else if (n <= -1 && n >= -127) { const value = data[inIndex++]; for (let index = 0; index < -n + 1 && outIndex < endOfSegment; ++index) { out[outIndex] = value; outIndex += imageFrame.samplesPerPixel; } } } } imageFrame.pixelData = new Uint8Array(outFrame); return imageFrame; } function decode8Planar(imageFrame, pixelData) { const frameData = pixelData; const frameSize = imageFrame.rows * imageFrame.columns; const outFrame = new ArrayBuffer(frameSize * imageFrame.samplesPerPixel); const header = new DataView(frameData.buffer, frameData.byteOffset); const data = new Int8Array(frameData.buffer, frameData.byteOffset); const out = new Int8Array(outFrame); let outIndex = 0; const numberSegments = header.getInt32(0, true); for (let s = 0; s < numberSegments; ++s) { outIndex = s * frameSize; let inIndex = header.getInt32((s + 1) * 4, true); let maxIndex = header.getInt32((s + 2) * 4, true); if (maxIndex === 0) { maxIndex = frameData.length; } const endOfSegment = frameSize * numberSegments; while (inIndex < maxIndex) { const n = data[inIndex++]; if (n >= 0 && n <= 127) { for (let index = 0; index < n + 1 && outIndex < endOfSegment; ++index) { out[outIndex] = data[inIndex++]; outIndex++; } } else if (n <= -1 && n >= -127) { const value = data[inIndex++]; for (let index = 0; index < -n + 1 && outIndex < endOfSegment; ++index) { out[outIndex] = value; outIndex++; } } } } imageFrame.pixelData = new Uint8Array(outFrame); return imageFrame; } function decode16(imageFrame, pixelData) { const frameData = pixelData; const frameSize = imageFrame.rows * imageFrame.columns; const outFrame = new ArrayBuffer(frameSize * imageFrame.samplesPerPixel * 2); const header = new DataView(frameData.buffer, frameData.byteOffset); const data = new Int8Array(frameData.buffer, frameData.byteOffset); const out = new Int8Array(outFrame); const numberSegments = header.getInt32(0, true); for (let s = 0; s < numberSegments; ++s) { let outIndex = 0; const highByte = s === 0 ? 1 : 0; let inIndex = header.getInt32((s + 1) * 4, true); let maxIndex = header.getInt32((s + 2) * 4, true); if (maxIndex === 0) { maxIndex = frameData.length; } while (inIndex < maxIndex) { const n = data[inIndex++]; if (n >= 0 && n <= 127) { for (let index = 0; index < n + 1 && outIndex < frameSize; ++index) { out[outIndex * 2 + highByte] = data[inIndex++]; outIndex++; } } else if (n <= -1 && n >= -127) { const value = data[inIndex++]; for (let index = 0; index < -n + 1 && outIndex < frameSize; ++index) { out[outIndex * 2 + highByte] = value; outIndex++; } } } } imageFrame.pixelData = imageFrame.pixelRepresentation === 0 ? new Uint16Array(outFrame) : new Int16Array(outFrame); return imageFrame; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (decodeRLE); /***/ }, /***/ 67151 /*!*********************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/getMinMax.js ***! \*********************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getMinMax(storedPixelData) { let min = storedPixelData[0]; let max = storedPixelData[0]; let storedPixel; const numberPixels = storedPixelData.length; for (let index = 1; index < numberPixels; index++) { storedPixel = storedPixelData[index]; min = Math.min(min, storedPixel); max = Math.max(max, storedPixel); } return { min, max }; } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getMinMax); /***/ }, /***/ 52783 /*!**************************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/getPixelDataTypeFromMinMax.js ***! \**************************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ getPixelDataTypeFromMinMax), /* harmony export */ validatePixelDataType: () => (/* binding */ validatePixelDataType) /* harmony export */ }); function getPixelDataTypeFromMinMax(min, max) { let pixelDataType; if (Number.isInteger(min) && Number.isInteger(max)) { if (min >= 0) { if (max <= 255) { pixelDataType = Uint8Array; } else if (max <= 65_535) { pixelDataType = Uint16Array; } } else { if (min >= -128 && max <= 127) { pixelDataType = Int8Array; } else if (min >= -32_768 && max <= 32_767) { pixelDataType = Int16Array; } } } return pixelDataType || Float32Array; } function validatePixelDataType(min, max, type) { const pixelDataType = getPixelDataTypeFromMinMax(min, max); return pixelDataType === type; } /***/ }, /***/ 93109 /*!************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/isColorImage.js ***! \************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(photoMetricInterpretation) { return photoMetricInterpretation === 'RGB' || photoMetricInterpretation === 'PALETTE COLOR' || photoMetricInterpretation === 'YBR_FULL' || photoMetricInterpretation === 'YBR_FULL_422' || photoMetricInterpretation === 'YBR_PARTIAL_422' || photoMetricInterpretation === 'YBR_PARTIAL_420' || photoMetricInterpretation === 'YBR_RCT' || photoMetricInterpretation === 'YBR_ICT'; } /***/ }, /***/ 53076 /*!****************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/scaling/bilinear.js ***! \****************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ bilinear) /* harmony export */ }); function bilinear(source, destination) { const { rows: sourceRows, columns: sourceColumns, data: sourceData } = source; const { rows, columns, data } = destination; const xSource1Off = []; const xSource2Off = []; const xFrac = []; for (let x = 0; x < columns; x++) { const xSource = x * (sourceColumns - 1) / (columns - 1); xSource1Off[x] = Math.floor(xSource); xSource2Off[x] = Math.min(xSource1Off[x] + 1, sourceColumns - 1); xFrac[x] = xSource - xSource1Off[x]; } for (let y = 0; y < rows; y++) { const ySource = y * (sourceRows - 1) / (rows - 1); const ySource1Off = Math.floor(ySource) * sourceColumns; const ySource2Off = Math.min(ySource1Off + sourceColumns, (sourceRows - 1) * sourceColumns); const yFrac = ySource - Math.floor(ySource); const yFracInv = 1 - yFrac; const yOff = y * columns; for (let x = 0; x < columns; x++) { const p00 = sourceData[ySource1Off + xSource1Off[x]]; const p10 = sourceData[ySource1Off + xSource2Off[x]]; const p01 = sourceData[ySource2Off + xSource1Off[x]]; const p11 = sourceData[ySource2Off + xSource2Off[x]]; const xFracInv = 1 - xFrac[x]; data[yOff + x] = (p00 * xFracInv + p10 * xFrac[x]) * yFracInv + (p01 * xFracInv + p11 * xFrac[x]) * yFrac; } } return data; } /***/ }, /***/ 2964 /*!*****************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/scaling/replicate.js ***! \*****************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ replicate) /* harmony export */ }); function replicate(source, destination) { const { rows: sourceRows, columns: sourceColumns, pixelData: sourceData, samplesPerPixel = 1 } = source; const { rows, columns, pixelData } = destination; const xSource1Off = []; for (let x = 0; x < columns; x++) { const xSource = x * (sourceColumns - 1) / (columns - 1); xSource1Off[x] = Math.floor(xSource) * samplesPerPixel; } for (let y = 0; y < rows; y++) { const ySource = y * (sourceRows - 1) / (rows - 1); const ySource1Off = Math.floor(ySource) * sourceColumns * samplesPerPixel; const yOff = y * columns; for (let x = 0; x < columns; x++) { for (let sample = 0; sample < samplesPerPixel; sample++) { pixelData[yOff + x + sample] = sourceData[ySource1Off + xSource1Off[x] + sample]; } } } return pixelData; } /***/ }, /***/ 91344 /*!******************************************************************!*\ !*** ./libs/dicom-image-loader-dev/shared/scaling/scaleArray.js ***! \******************************************************************/ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ scaleArray) /* harmony export */ }); function scaleArray(array, scalingParameters) { const arrayLength = array.length; const { rescaleSlope, rescaleIntercept, suvbw } = scalingParameters; if (scalingParameters.modality === 'PT' && typeof suvbw === 'number' && !isNaN(suvbw)) { for (let index = 0; index < arrayLength; index++) { array[index] = suvbw * (array[index] * rescaleSlope + rescaleIntercept); } } else { for (let index = 0; index < arrayLength; index++) { array[index] = array[index] * rescaleSlope + rescaleIntercept; } } return true; } /***/ } }, /******/ __webpack_require__ => { // webpackRuntimeModules /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) /******/ __webpack_require__.O(0, ["vendor"], () => (__webpack_exec__(97283))); /******/ var __webpack_exports__ = __webpack_require__.O(); /******/ } ]); //# sourceMappingURL=main.js.map