@rtsee/ngx 0.0.117 → 0.0.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -54,7 +54,7 @@ import { Tag } from 'primeng/tag';
54
54
  import { SelectButton } from 'primeng/selectbutton';
55
55
  import { RTSeeRoutesList } from '@rtsee/factory';
56
56
  import { Avatar } from 'primeng/avatar';
57
- import { Image } from 'primeng/image';
57
+ import { Image as Image$1 } from 'primeng/image';
58
58
  import { PanelMenu } from 'primeng/panelmenu';
59
59
  import { Menu } from 'primeng/menu';
60
60
  import { Password } from 'primeng/password';
@@ -1961,11 +1961,11 @@ class RatingComponent {
1961
1961
  this.init();
1962
1962
  }
1963
1963
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1964
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RatingComponent, isStandalone: true, selector: "rtsee-rating", inputs: { config: "config", rate: "rate" }, ngImport: i0, template: "<div class=\"rtsee-rating\">\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: DecimalPipe, name: "number" }] }); }
1964
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RatingComponent, isStandalone: true, selector: "rtsee-rating", inputs: { config: "config", rate: "rate" }, ngImport: i0, template: "<div\n class=\"rtsee-rating\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"reviewRating\"\n itemscope\n itemtype=\"https://schema.org/Rating\"\n>\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\" itemprop=\"ratingValue\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: DecimalPipe, name: "number" }] }); }
1965
1965
  }
1966
1966
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingComponent, decorators: [{
1967
1967
  type: Component,
1968
- args: [{ selector: 'rtsee-rating', imports: [NgClass, DecimalPipe], template: "<div class=\"rtsee-rating\">\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n" }]
1968
+ args: [{ selector: 'rtsee-rating', imports: [NgClass, DecimalPipe], template: "<div\n class=\"rtsee-rating\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"reviewRating\"\n itemscope\n itemtype=\"https://schema.org/Rating\"\n>\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\" itemprop=\"ratingValue\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n" }]
1969
1969
  }], propDecorators: { config: [{
1970
1970
  type: Input
1971
1971
  }], rate: [{
@@ -2122,7 +2122,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
2122
2122
  }] } });
2123
2123
 
2124
2124
  class MediaWidgetComponent {
2125
- constructor() {
2125
+ constructor(cdr) {
2126
+ this.cdr = cdr;
2126
2127
  this.showCost = true;
2127
2128
  this.visibleImages = [];
2128
2129
  this.hiddenCount = 0;
@@ -2130,6 +2131,7 @@ class MediaWidgetComponent {
2130
2131
  this.downloadingUrl = null;
2131
2132
  this.loadedImageUrls = new Set();
2132
2133
  this.erroredImageUrls = new Set();
2134
+ this.preloadingImageUrls = new Set();
2133
2135
  this.MAX_GRID = 4;
2134
2136
  }
2135
2137
  ngOnInit() {
@@ -2142,26 +2144,102 @@ class MediaWidgetComponent {
2142
2144
  this.updateVisibleImages();
2143
2145
  }
2144
2146
  }
2145
- /** Downsized version for rendering, the original otherwise */
2147
+ get isAiGenerated() {
2148
+ return Boolean(this.message?.from?.isAgent ||
2149
+ this.message?.cost ||
2150
+ this.message?.data?.flowId ||
2151
+ this.message?.data?.requestId ||
2152
+ this.message?.data?.awaitingGeneration);
2153
+ }
2154
+ get isAwaitingGeneration() {
2155
+ return !this.hasImages && !this.hasVideo;
2156
+ }
2157
+ get awaitingPlaceholderText() {
2158
+ return this.message?.data?.placeholderText || 'Generating image...';
2159
+ }
2160
+ /** Downsized version for rendering/export, the original otherwise */
2146
2161
  previewUrl(img) {
2147
2162
  return img.smallVersionUrl || img.url;
2148
2163
  }
2164
+ /**
2165
+ * URL bound to the <img> element:
2166
+ * - While the full-size image is already loaded and `smallVersionUrl` is being preloaded,
2167
+ * keep displaying the loaded full-size `img.url` so there is no blank flicker,
2168
+ * then swap to `img.smallVersionUrl` as soon as it finishes preloading.
2169
+ */
2170
+ displayUrl(img) {
2171
+ if (img.smallVersionUrl) {
2172
+ if (this.loadedImageUrls.has(img.smallVersionUrl)) {
2173
+ return img.smallVersionUrl;
2174
+ }
2175
+ if (this.loadedImageUrls.has(img.url)) {
2176
+ this.preloadSmallVersion(img.smallVersionUrl);
2177
+ return img.url;
2178
+ }
2179
+ return img.smallVersionUrl;
2180
+ }
2181
+ return img.url;
2182
+ }
2183
+ /**
2184
+ * True while the full-size image is being compressed/uploaded by ImageCropper/Uploader
2185
+ * or while the resulting `smallVersionUrl` is preloading to replace the full-size image.
2186
+ */
2187
+ isProcessingImage(img) {
2188
+ const optimizingMessage = Boolean(this.message?.data?.isOptimizingImages ||
2189
+ this.messenger?.isOptimizingMessageImages?.(this.message?.id));
2190
+ if (optimizingMessage && !img.smallVersionUrl) {
2191
+ return true;
2192
+ }
2193
+ if (img.smallVersionUrl &&
2194
+ this.loadedImageUrls.has(img.url) &&
2195
+ !this.loadedImageUrls.has(img.smallVersionUrl) &&
2196
+ !this.erroredImageUrls.has(img.smallVersionUrl)) {
2197
+ return true;
2198
+ }
2199
+ return false;
2200
+ }
2149
2201
  isImageLoaded(img) {
2150
- const url = this.previewUrl(img);
2202
+ const url = this.displayUrl(img);
2151
2203
  return this.loadedImageUrls.has(url);
2152
2204
  }
2153
2205
  isImageError(img) {
2154
- const url = this.previewUrl(img);
2206
+ const url = this.displayUrl(img);
2155
2207
  return this.erroredImageUrls.has(url);
2156
2208
  }
2157
2209
  onImageLoad(img) {
2158
- const url = this.previewUrl(img);
2210
+ const url = this.displayUrl(img);
2159
2211
  this.loadedImageUrls.add(url);
2212
+ if (img.smallVersionUrl && url === img.url && !this.loadedImageUrls.has(img.smallVersionUrl)) {
2213
+ this.preloadSmallVersion(img.smallVersionUrl);
2214
+ }
2160
2215
  }
2161
2216
  onImageError(img) {
2162
- const url = this.previewUrl(img);
2217
+ const url = this.displayUrl(img);
2163
2218
  this.erroredImageUrls.add(url);
2164
2219
  }
2220
+ preloadSmallVersion(smallUrl) {
2221
+ if (typeof window === 'undefined' ||
2222
+ !smallUrl ||
2223
+ this.loadedImageUrls.has(smallUrl) ||
2224
+ this.preloadingImageUrls.has(smallUrl)) {
2225
+ return;
2226
+ }
2227
+ this.preloadingImageUrls.add(smallUrl);
2228
+ const preloader = new Image();
2229
+ preloader.onload = () => {
2230
+ this.preloadingImageUrls.delete(smallUrl);
2231
+ this.loadedImageUrls.add(smallUrl);
2232
+ this.cdr.markForCheck();
2233
+ this.cdr.detectChanges();
2234
+ };
2235
+ preloader.onerror = () => {
2236
+ this.preloadingImageUrls.delete(smallUrl);
2237
+ this.erroredImageUrls.add(smallUrl);
2238
+ this.cdr.markForCheck();
2239
+ this.cdr.detectChanges();
2240
+ };
2241
+ preloader.src = smallUrl;
2242
+ }
2165
2243
  async downloadOriginal(event, img) {
2166
2244
  event.stopPropagation();
2167
2245
  event.preventDefault();
@@ -2215,11 +2293,12 @@ class MediaWidgetComponent {
2215
2293
  sendToIllustrator(event, img) {
2216
2294
  event.stopPropagation();
2217
2295
  event.preventDefault();
2218
- if (typeof window !== 'undefined' && img?.url) {
2219
- // Retain AWS presigned URL so Illustrator can render the image preview!
2296
+ const targetUrl = this.previewUrl(img);
2297
+ if (typeof window !== 'undefined' && targetUrl) {
2298
+ // Use the web-optimized URL (smallVersionUrl when available) for Illustrator & Story Editor
2220
2299
  window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.SET_IMAGE_FOR_REVIEW, {
2221
2300
  detail: {
2222
- imageUrl: img.url,
2301
+ imageUrl: targetUrl,
2223
2302
  prompt: img.name || (typeof this.message.text === 'string' ? this.message.text : '') || '',
2224
2303
  source: 'messenger',
2225
2304
  },
@@ -2229,11 +2308,12 @@ class MediaWidgetComponent {
2229
2308
  addToContext(event, img) {
2230
2309
  event.stopPropagation();
2231
2310
  event.preventDefault();
2232
- if (typeof window !== 'undefined' && img?.url) {
2311
+ const targetUrl = this.previewUrl(img);
2312
+ if (typeof window !== 'undefined' && targetUrl) {
2233
2313
  window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.ADD_IMAGE_TO_CONTEXT, {
2234
2314
  detail: {
2235
2315
  id: 'chat-img-' + Math.random().toString(36).substring(2, 9),
2236
- imageUrl: img.url,
2316
+ imageUrl: targetUrl,
2237
2317
  title: img.name || 'Chat image',
2238
2318
  description: (typeof this.message.text === 'string' ? this.message.text : '') || '',
2239
2319
  visualDescription: '',
@@ -2244,7 +2324,11 @@ class MediaWidgetComponent {
2244
2324
  }
2245
2325
  }
2246
2326
  updateVisibleImages() {
2247
- const all = this.message.images || [];
2327
+ const rawImages = this.message?.images || [];
2328
+ // AI-generated messages only show a single image; user messages can show multiple images
2329
+ const all = this.isAiGenerated && rawImages.length > 1
2330
+ ? [rawImages[rawImages.length - 1]]
2331
+ : rawImages;
2248
2332
  if (this.showAll || all.length <= this.MAX_GRID) {
2249
2333
  this.visibleImages = all;
2250
2334
  this.hiddenCount = 0;
@@ -2253,27 +2337,33 @@ class MediaWidgetComponent {
2253
2337
  this.visibleImages = all.slice(0, this.MAX_GRID);
2254
2338
  this.hiddenCount = all.length - this.MAX_GRID;
2255
2339
  }
2340
+ for (const img of this.visibleImages) {
2341
+ if (img.smallVersionUrl && this.loadedImageUrls.has(img.url) && !this.loadedImageUrls.has(img.smallVersionUrl)) {
2342
+ this.preloadSmallVersion(img.smallVersionUrl);
2343
+ }
2344
+ }
2256
2345
  }
2257
2346
  notifyRequestedGeneration() {
2258
2347
  const reqId = this.message?.data?.requestId;
2259
- if (reqId && this.visibleImages.length > 0 && typeof window !== 'undefined') {
2348
+ const optimizedUrl = this.visibleImages[0]?.smallVersionUrl;
2349
+ if (reqId && optimizedUrl && typeof window !== 'undefined') {
2260
2350
  window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.REQUESTED_GENERATION_SUCCEED, {
2261
2351
  detail: {
2262
2352
  requestId: reqId,
2263
- imageUrl: this.visibleImages[0].url,
2353
+ imageUrl: optimizedUrl,
2264
2354
  messageId: this.message.id,
2265
2355
  chatId: this.chat?.id,
2266
2356
  },
2267
2357
  }));
2268
2358
  }
2269
2359
  }
2270
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2271
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MediaWidgetComponent, isStandalone: true, selector: "rtsee-media-widget", inputs: { message: "message", messenger: "messenger", chat: "chat", showCost: "showCost" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || img.url) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"previewUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image:hover{transform:scale(1.02)}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CostDisplayComponent, selector: "rtsee-cost-display", inputs: ["cost"] }] }); }
2360
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2361
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MediaWidgetComponent, isStandalone: true, selector: "rtsee-media-widget", inputs: { message: "message", messenger: "messenger", chat: "chat", showCost: "showCost" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Awaiting AI image generation preloader -->\n @if (isAwaitingGeneration) {\n <div class=\"rts-media-images rts-media-grid-1\">\n <div class=\"rts-media-image-wrapper\">\n <div class=\"rts-media-placeholder\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ awaitingPlaceholderText }}</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || $index) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"displayUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n [class.rts-media-image-processing]=\"isImageLoaded(img) && isProcessingImage(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img) && isProcessingImage(img)) {\n <div class=\"rts-media-processing-overlay\">\n <div class=\"rts-media-processing-badge\">\n <span class=\"rts-media-processing-spinner\"></span>\n <span class=\"rts-media-processing-text\">processing...</span>\n </div>\n </div>\n }\n\n @if (isImageLoaded(img) && !isProcessingImage(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image.rts-media-image-processing{filter:brightness(.75)}.rts-media-image:hover{transform:scale(1.02)}.rts-media-processing-overlay{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;background:#0f0f1959;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);pointer-events:none}.rts-media-processing-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;background:#12121ce0;border:1px solid rgba(168,85,247,.45);box-shadow:0 4px 16px #00000073}.rts-media-processing-spinner{width:14px;height:14px;border-radius:50%;border:2px solid rgba(192,132,252,.28);border-top-color:#c084fc;animation:rts-media-spin .8s linear infinite}.rts-media-processing-text{font-size:12px;font-weight:600;color:#f3e8ff;letter-spacing:.02em}@keyframes rts-media-spin{to{transform:rotate(360deg)}}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CostDisplayComponent, selector: "rtsee-cost-display", inputs: ["cost"] }] }); }
2272
2362
  }
2273
2363
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, decorators: [{
2274
2364
  type: Component,
2275
- args: [{ selector: 'rtsee-media-widget', standalone: true, imports: [NgClass, CostDisplayComponent], template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || img.url) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"previewUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image:hover{transform:scale(1.02)}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"] }]
2276
- }], propDecorators: { message: [{
2365
+ args: [{ selector: 'rtsee-media-widget', standalone: true, imports: [NgClass, CostDisplayComponent], template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Awaiting AI image generation preloader -->\n @if (isAwaitingGeneration) {\n <div class=\"rts-media-images rts-media-grid-1\">\n <div class=\"rts-media-image-wrapper\">\n <div class=\"rts-media-placeholder\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ awaitingPlaceholderText }}</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || $index) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"displayUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n [class.rts-media-image-processing]=\"isImageLoaded(img) && isProcessingImage(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img) && isProcessingImage(img)) {\n <div class=\"rts-media-processing-overlay\">\n <div class=\"rts-media-processing-badge\">\n <span class=\"rts-media-processing-spinner\"></span>\n <span class=\"rts-media-processing-text\">processing...</span>\n </div>\n </div>\n }\n\n @if (isImageLoaded(img) && !isProcessingImage(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image.rts-media-image-processing{filter:brightness(.75)}.rts-media-image:hover{transform:scale(1.02)}.rts-media-processing-overlay{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;background:#0f0f1959;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);pointer-events:none}.rts-media-processing-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;background:#12121ce0;border:1px solid rgba(168,85,247,.45);box-shadow:0 4px 16px #00000073}.rts-media-processing-spinner{width:14px;height:14px;border-radius:50%;border:2px solid rgba(192,132,252,.28);border-top-color:#c084fc;animation:rts-media-spin .8s linear infinite}.rts-media-processing-text{font-size:12px;font-weight:600;color:#f3e8ff;letter-spacing:.02em}@keyframes rts-media-spin{to{transform:rotate(360deg)}}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"] }]
2366
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { message: [{
2277
2367
  type: Input
2278
2368
  }], messenger: [{
2279
2369
  type: Input
@@ -2639,6 +2729,9 @@ class StorytellerStoryLinkStepComponent {
2639
2729
  return this.story.storyId ? `/story/${this.story.storyId}` : '';
2640
2730
  }
2641
2731
  get kicker() {
2732
+ if (this.story.repairedGrammar !== undefined || this.story.updatedSlidesCount !== undefined) {
2733
+ return 'Story repaired';
2734
+ }
2642
2735
  const language = this.story.language ? getStoryTranslatorLanguage(this.story.language) : undefined;
2643
2736
  return language ? `Translated to ${language.nativeName}` : 'Your story is ready';
2644
2737
  }
@@ -2658,7 +2751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
2658
2751
  type: Input
2659
2752
  }] } });
2660
2753
 
2661
- const SEARCH_DEBOUNCE_MS = 250;
2754
+ const SEARCH_DEBOUNCE_MS$1 = 250;
2662
2755
  /**
2663
2756
  * Story Translator step 1: pick a story (autocomplete by name) and the target language.
2664
2757
  */
@@ -2672,10 +2765,13 @@ class StoryTranslatorFormStepComponent {
2672
2765
  storyQuery: new FormControl(''),
2673
2766
  storyId: new FormControl('', Validators.required),
2674
2767
  language: new FormControl('', Validators.required),
2768
+ fromScratch: new FormControl(false),
2675
2769
  agentId: new FormControl('', Validators.required),
2676
2770
  /* eslint-enable */
2677
2771
  });
2678
2772
  this.selectedStory = null;
2773
+ this.hasExistingTranslation = false;
2774
+ this.checkingTranslations = false;
2679
2775
  this.suggestions = [];
2680
2776
  this.suggestionsOpened = false;
2681
2777
  this.highlightedIndex = 0;
@@ -2683,6 +2779,7 @@ class StoryTranslatorFormStepComponent {
2683
2779
  this.searchError = null;
2684
2780
  this.searchTimer = null;
2685
2781
  this.searchRequestId = 0;
2782
+ this.translationCheckRequestId = 0;
2686
2783
  this.onChangedBound = () => this.onWorkflowChanged();
2687
2784
  }
2688
2785
  get agents() {
@@ -2722,10 +2819,11 @@ class StoryTranslatorFormStepComponent {
2722
2819
  // typing invalidates the previous selection
2723
2820
  if (this.selectedStory) {
2724
2821
  this.selectedStory = null;
2725
- this.form.get('storyId')?.setValue('');
2822
+ this.hasExistingTranslation = false;
2823
+ this.form.patchValue({ storyId: '', fromScratch: false }, { emitEvent: false });
2726
2824
  }
2727
2825
  this.suggestionsOpened = true;
2728
- this.scheduleSearch(SEARCH_DEBOUNCE_MS);
2826
+ this.scheduleSearch(SEARCH_DEBOUNCE_MS$1);
2729
2827
  }
2730
2828
  onStoryKeydown(event) {
2731
2829
  if (!this.suggestionsOpened || !this.suggestions.length) {
@@ -2759,20 +2857,29 @@ class StoryTranslatorFormStepComponent {
2759
2857
  return;
2760
2858
  }
2761
2859
  this.selectedStory = story;
2762
- this.form.patchValue({ storyId: story.id, storyQuery: story.name }, { emitEvent: false });
2860
+ this.form.patchValue({ storyId: story.id, storyQuery: story.name, fromScratch: false }, { emitEvent: false });
2763
2861
  this.form.get('storyId')?.markAsTouched();
2764
2862
  this.suggestionsOpened = false;
2863
+ void this.checkExistingTranslation();
2765
2864
  }
2766
2865
  clearStory() {
2767
2866
  if (this.readonly) {
2768
2867
  return;
2769
2868
  }
2770
2869
  this.selectedStory = null;
2771
- this.form.patchValue({ storyId: '', storyQuery: '' }, { emitEvent: false });
2870
+ this.hasExistingTranslation = false;
2871
+ this.form.patchValue({ storyId: '', storyQuery: '', fromScratch: false }, { emitEvent: false });
2772
2872
  this.suggestionsOpened = true;
2773
2873
  this.scheduleSearch(0);
2774
2874
  setTimeout(() => this.storyInput?.nativeElement.focus());
2775
2875
  }
2876
+ onLanguageChange() {
2877
+ if (this.readonly) {
2878
+ return;
2879
+ }
2880
+ this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
2881
+ void this.checkExistingTranslation();
2882
+ }
2776
2883
  onDocumentMouseDown(event) {
2777
2884
  if (this.suggestionsOpened && !this.host.nativeElement.contains(event.target)) {
2778
2885
  this.suggestionsOpened = false;
@@ -2791,6 +2898,7 @@ class StoryTranslatorFormStepComponent {
2791
2898
  storyName: this.selectedStory.name,
2792
2899
  language: this.form.get('language')?.value,
2793
2900
  agentId: this.form.get('agentId')?.value,
2901
+ fromScratch: this.hasExistingTranslation ? !!this.form.get('fromScratch')?.value : false,
2794
2902
  });
2795
2903
  }
2796
2904
  cancel() {
@@ -2852,7 +2960,19 @@ class StoryTranslatorFormStepComponent {
2852
2960
  const output = this.step?.output;
2853
2961
  if (output?.storyId) {
2854
2962
  this.selectedStory = { id: output.storyId, name: output.storyName || output.storyId };
2855
- this.form.patchValue({ storyId: output.storyId, storyQuery: output.storyName || '', language: output.language, agentId: output.agentId }, { emitEvent: false });
2963
+ this.form.patchValue({
2964
+ storyId: output.storyId,
2965
+ storyQuery: output.storyName || '',
2966
+ language: output.language,
2967
+ fromScratch: !!output.fromScratch,
2968
+ agentId: output.agentId,
2969
+ }, { emitEvent: false });
2970
+ if (output.fromScratch) {
2971
+ this.hasExistingTranslation = true;
2972
+ }
2973
+ else {
2974
+ void this.checkExistingTranslation(true);
2975
+ }
2856
2976
  }
2857
2977
  if (this.readonly) {
2858
2978
  this.suggestionsOpened = false;
@@ -2862,12 +2982,315 @@ class StoryTranslatorFormStepComponent {
2862
2982
  this.form.enable({ emitEvent: false });
2863
2983
  }
2864
2984
  }
2985
+ async checkExistingTranslation(preserveCheckboxValue = false) {
2986
+ const storyId = this.selectedStory?.id;
2987
+ const rawLang = this.form.get('language')?.value || '';
2988
+ const langInfo = getStoryTranslatorLanguage(rawLang);
2989
+ const languageKey = langInfo?.code || rawLang;
2990
+ if (!storyId || !languageKey) {
2991
+ this.hasExistingTranslation = false;
2992
+ this.checkingTranslations = false;
2993
+ if (!preserveCheckboxValue) {
2994
+ this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
2995
+ }
2996
+ this.cdr.markForCheck();
2997
+ return;
2998
+ }
2999
+ const requestId = ++this.translationCheckRequestId;
3000
+ this.checkingTranslations = true;
3001
+ const aliases = this.selectedStory?.aliases || [];
3002
+ const hasAliasForLang = aliases.some((a) => {
3003
+ const norm = getStoryTranslatorLanguage(a.languageKey)?.code || a.languageKey;
3004
+ return norm === languageKey;
3005
+ });
3006
+ try {
3007
+ const translations = this.messenger?.ozzy
3008
+ ? await this.messenger.ozzy.getStoryTranslations(storyId)
3009
+ : [];
3010
+ if (requestId !== this.translationCheckRequestId) {
3011
+ return;
3012
+ }
3013
+ const hasStoryTranslation = translations.some((t) => {
3014
+ const norm = getStoryTranslatorLanguage(t.languageKey)?.code || t.languageKey;
3015
+ return norm === languageKey;
3016
+ });
3017
+ this.hasExistingTranslation = hasAliasForLang || hasStoryTranslation;
3018
+ if (!this.hasExistingTranslation && !preserveCheckboxValue) {
3019
+ this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
3020
+ }
3021
+ }
3022
+ catch {
3023
+ if (requestId !== this.translationCheckRequestId) {
3024
+ return;
3025
+ }
3026
+ this.hasExistingTranslation = hasAliasForLang;
3027
+ }
3028
+ finally {
3029
+ if (requestId === this.translationCheckRequestId) {
3030
+ this.checkingTranslations = false;
3031
+ this.cdr.detectChanges();
3032
+ }
3033
+ }
3034
+ }
2865
3035
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryTranslatorFormStepComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
2866
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryTranslatorFormStepComponent, isStandalone: true, selector: "rtsee-story-translator-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
3036
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryTranslatorFormStepComponent, isStandalone: true, selector: "rtsee-story-translator-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n (change)=\"onLanguageChange()\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n @if (hasExistingTranslation) {\n <label class=\"rts-st-checkbox-row\" for=\"story-translator-from-scratch-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"fromScratch\"\n id=\"story-translator-from-scratch-{{ step.id }}\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">From scratch</span>\n <span class=\"rts-st-checkbox-desc\">Overwrite existing {{ selectedLanguage?.nativeName || '' }} translations for all story elements</span>\n </span>\n </label>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
2867
3037
  }
2868
3038
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryTranslatorFormStepComponent, decorators: [{
2869
3039
  type: Component,
2870
- args: [{ selector: 'rtsee-story-translator-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
3040
+ args: [{ selector: 'rtsee-story-translator-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n (change)=\"onLanguageChange()\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n @if (hasExistingTranslation) {\n <label class=\"rts-st-checkbox-row\" for=\"story-translator-from-scratch-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"fromScratch\"\n id=\"story-translator-from-scratch-{{ step.id }}\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">From scratch</span>\n <span class=\"rts-st-checkbox-desc\">Overwrite existing {{ selectedLanguage?.nativeName || '' }} translations for all story elements</span>\n </span>\n </label>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
3041
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { step: [{
3042
+ type: Input
3043
+ }], workflow: [{
3044
+ type: Input
3045
+ }], chat: [{
3046
+ type: Input
3047
+ }], messenger: [{
3048
+ type: Input
3049
+ }], storyInput: [{
3050
+ type: ViewChild,
3051
+ args: ['storyInput']
3052
+ }], onDocumentMouseDown: [{
3053
+ type: HostListener,
3054
+ args: ['document:mousedown', ['$event']]
3055
+ }] } });
3056
+
3057
+ const SEARCH_DEBOUNCE_MS = 250;
3058
+ /**
3059
+ * Story Repair step 1 (#RepairStory):
3060
+ * - Pick a story (autocomplete by name)
3061
+ * - Choose repair options via 4 checkboxes (Grammar & Flow, Characters, Artifacts, Locations), all checked by default
3062
+ * - Pick an agent
3063
+ */
3064
+ class StoryRepairFormStepComponent {
3065
+ constructor(cdr, host) {
3066
+ this.cdr = cdr;
3067
+ this.host = host;
3068
+ this.form = new FormGroup({
3069
+ /* eslint-disable */
3070
+ storyQuery: new FormControl(''),
3071
+ storyId: new FormControl('', Validators.required),
3072
+ grammarAndFlow: new FormControl(true),
3073
+ characters: new FormControl(true),
3074
+ artifacts: new FormControl(true),
3075
+ locations: new FormControl(true),
3076
+ agentId: new FormControl('', Validators.required),
3077
+ /* eslint-enable */
3078
+ });
3079
+ this.selectedStory = null;
3080
+ this.suggestions = [];
3081
+ this.suggestionsOpened = false;
3082
+ this.highlightedIndex = 0;
3083
+ this.searchInProgress = false;
3084
+ this.searchError = null;
3085
+ this.optionsTouched = false;
3086
+ this.searchTimer = null;
3087
+ this.searchRequestId = 0;
3088
+ this.onChangedBound = () => this.onWorkflowChanged();
3089
+ }
3090
+ get agents() {
3091
+ return (this.chat?.members || []).filter((m) => m.isAgent);
3092
+ }
3093
+ get readonly() {
3094
+ return !this.step?.isActive || !!this.workflow?.submitInProgress;
3095
+ }
3096
+ get canCancel() {
3097
+ return !!this.workflow?.isDraft && !this.workflow?.submitInProgress && !!this.messenger;
3098
+ }
3099
+ get hasAtLeastOneOption() {
3100
+ const opts = this.currentOptions;
3101
+ return opts.grammarAndFlow || opts.characters || opts.artifacts || opts.locations;
3102
+ }
3103
+ get currentOptions() {
3104
+ return {
3105
+ grammarAndFlow: !!this.form.get('grammarAndFlow')?.value,
3106
+ characters: !!this.form.get('characters')?.value,
3107
+ artifacts: !!this.form.get('artifacts')?.value,
3108
+ locations: !!this.form.get('locations')?.value,
3109
+ };
3110
+ }
3111
+ ngOnInit() {
3112
+ this.workflow?.on(OzzyWorkflowClientEvents.CHANGED, this.onChangedBound);
3113
+ const agents = this.agents;
3114
+ if (agents.length === 1) {
3115
+ this.form.get('agentId')?.setValue(agents[0].id);
3116
+ }
3117
+ this.syncWithStep();
3118
+ }
3119
+ ngOnDestroy() {
3120
+ this.workflow?.off(OzzyWorkflowClientEvents.CHANGED, this.onChangedBound);
3121
+ this.clearSearchTimer();
3122
+ }
3123
+ onStoryFocus() {
3124
+ if (this.readonly) {
3125
+ return;
3126
+ }
3127
+ this.suggestionsOpened = true;
3128
+ if (!this.suggestions.length) {
3129
+ this.scheduleSearch(0);
3130
+ }
3131
+ }
3132
+ onStoryInput() {
3133
+ if (this.selectedStory) {
3134
+ this.selectedStory = null;
3135
+ this.form.get('storyId')?.setValue('');
3136
+ }
3137
+ this.suggestionsOpened = true;
3138
+ this.scheduleSearch(SEARCH_DEBOUNCE_MS);
3139
+ }
3140
+ onStoryKeydown(event) {
3141
+ if (!this.suggestionsOpened || !this.suggestions.length) {
3142
+ if (event.key === 'ArrowDown') {
3143
+ this.suggestionsOpened = true;
3144
+ this.scheduleSearch(0);
3145
+ }
3146
+ return;
3147
+ }
3148
+ switch (event.key) {
3149
+ case 'ArrowDown':
3150
+ event.preventDefault();
3151
+ this.highlightedIndex = (this.highlightedIndex + 1) % this.suggestions.length;
3152
+ break;
3153
+ case 'ArrowUp':
3154
+ event.preventDefault();
3155
+ this.highlightedIndex =
3156
+ (this.highlightedIndex - 1 + this.suggestions.length) % this.suggestions.length;
3157
+ break;
3158
+ case 'Enter':
3159
+ event.preventDefault();
3160
+ this.selectStory(this.suggestions[this.highlightedIndex]);
3161
+ break;
3162
+ case 'Escape':
3163
+ event.preventDefault();
3164
+ this.suggestionsOpened = false;
3165
+ break;
3166
+ }
3167
+ }
3168
+ selectStory(story) {
3169
+ if (!story || this.readonly) {
3170
+ return;
3171
+ }
3172
+ this.selectedStory = story;
3173
+ this.form.patchValue({ storyId: story.id, storyQuery: story.name }, { emitEvent: false });
3174
+ this.form.get('storyId')?.markAsTouched();
3175
+ this.suggestionsOpened = false;
3176
+ }
3177
+ clearStory() {
3178
+ if (this.readonly) {
3179
+ return;
3180
+ }
3181
+ this.selectedStory = null;
3182
+ this.form.patchValue({ storyId: '', storyQuery: '' }, { emitEvent: false });
3183
+ this.suggestionsOpened = true;
3184
+ this.scheduleSearch(0);
3185
+ setTimeout(() => this.storyInput?.nativeElement.focus());
3186
+ }
3187
+ onOptionChanged() {
3188
+ this.optionsTouched = true;
3189
+ }
3190
+ onDocumentMouseDown(event) {
3191
+ if (this.suggestionsOpened && !this.host.nativeElement.contains(event.target)) {
3192
+ this.suggestionsOpened = false;
3193
+ }
3194
+ }
3195
+ submit() {
3196
+ if (this.readonly) {
3197
+ return;
3198
+ }
3199
+ this.optionsTouched = true;
3200
+ if (this.form.invalid || !this.selectedStory || !this.hasAtLeastOneOption) {
3201
+ this.form.markAllAsTouched();
3202
+ return;
3203
+ }
3204
+ void this.workflow.submitStep({
3205
+ storyId: this.selectedStory.id,
3206
+ storyName: this.selectedStory.name,
3207
+ agentId: this.form.get('agentId')?.value,
3208
+ options: this.currentOptions,
3209
+ });
3210
+ }
3211
+ cancel() {
3212
+ if (!this.canCancel) {
3213
+ return;
3214
+ }
3215
+ this.messenger?.discardDraftWorkflow(this.workflow);
3216
+ }
3217
+ isInvalid(name) {
3218
+ const control = this.form.get(name);
3219
+ return !!control && control.invalid && control.touched;
3220
+ }
3221
+ scheduleSearch(delay) {
3222
+ this.clearSearchTimer();
3223
+ this.searchTimer = setTimeout(() => void this.search(), delay);
3224
+ }
3225
+ clearSearchTimer() {
3226
+ if (this.searchTimer) {
3227
+ clearTimeout(this.searchTimer);
3228
+ this.searchTimer = null;
3229
+ }
3230
+ }
3231
+ async search() {
3232
+ if (!this.messenger) {
3233
+ return;
3234
+ }
3235
+ const requestId = ++this.searchRequestId;
3236
+ const query = this.form.get('storyQuery')?.value || '';
3237
+ this.searchInProgress = true;
3238
+ this.searchError = null;
3239
+ this.cdr.markForCheck();
3240
+ try {
3241
+ const stories = await this.messenger.ozzy.searchStories(query);
3242
+ if (requestId !== this.searchRequestId) {
3243
+ return;
3244
+ }
3245
+ this.suggestions = stories;
3246
+ this.highlightedIndex = 0;
3247
+ }
3248
+ catch (e) {
3249
+ if (requestId !== this.searchRequestId) {
3250
+ return;
3251
+ }
3252
+ this.suggestions = [];
3253
+ this.searchError = e?.friendlyMessage || e?.message || 'Failed to load stories.';
3254
+ }
3255
+ finally {
3256
+ if (requestId === this.searchRequestId) {
3257
+ this.searchInProgress = false;
3258
+ this.cdr.detectChanges();
3259
+ }
3260
+ }
3261
+ }
3262
+ onWorkflowChanged() {
3263
+ this.syncWithStep();
3264
+ this.cdr.detectChanges();
3265
+ }
3266
+ syncWithStep() {
3267
+ const output = this.step?.output;
3268
+ if (output?.storyId) {
3269
+ this.selectedStory = { id: output.storyId, name: output.storyName || output.storyId };
3270
+ this.form.patchValue({
3271
+ storyId: output.storyId,
3272
+ storyQuery: output.storyName || '',
3273
+ grammarAndFlow: output.options ? !!output.options.grammarAndFlow : true,
3274
+ characters: output.options ? !!output.options.characters : true,
3275
+ artifacts: output.options ? !!output.options.artifacts : true,
3276
+ locations: output.options ? !!output.options.locations : true,
3277
+ agentId: output.agentId,
3278
+ }, { emitEvent: false });
3279
+ }
3280
+ if (this.readonly) {
3281
+ this.suggestionsOpened = false;
3282
+ this.form.disable({ emitEvent: false });
3283
+ }
3284
+ else {
3285
+ this.form.enable({ emitEvent: false });
3286
+ }
3287
+ }
3288
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryRepairFormStepComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
3289
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryRepairFormStepComponent, isStandalone: true, selector: "rtsee-story-repair-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-repair-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-repair-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-repair-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n @if (selectedStory) {\n <div class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Repair options</span>\n <div class=\"rts-st-repair-options-grid\">\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-grammar-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"grammarAndFlow\"\n id=\"story-repair-grammar-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Grammar &amp; Flow</span>\n <span class=\"rts-st-checkbox-desc\">Fix typos, punctuation &amp; improve readability across story, slides &amp; entities</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-characters-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"characters\"\n id=\"story-repair-characters-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Characters</span>\n <span class=\"rts-st-checkbox-desc\">Add missing important characters and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-artifacts-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"artifacts\"\n id=\"story-repair-artifacts-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Artifacts</span>\n <span class=\"rts-st-checkbox-desc\">Add missing memorable objects and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-locations-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"locations\"\n id=\"story-repair-locations-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Locations</span>\n <span class=\"rts-st-checkbox-desc\">Add missing story locations and link them to slides</span>\n </span>\n </label>\n </div>\n @if (!hasAtLeastOneOption) {\n <div class=\"rts-storyteller-error\">Please select at least one option to repair.</div>\n }\n </div>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-repair-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-repair-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length || !selectedStory || !hasAtLeastOneOption\"\n id=\"story-repair-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Repairing\u2026\n } @else {\n \uD83D\uDEE0\uFE0F Repair Story\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n", ".rts-st-repair-options-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}@media (max-width: 480px){.rts-st-repair-options-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
3290
+ }
3291
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryRepairFormStepComponent, decorators: [{
3292
+ type: Component,
3293
+ args: [{ selector: 'rtsee-story-repair-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-repair-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-repair-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-repair-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n @if (selectedStory) {\n <div class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Repair options</span>\n <div class=\"rts-st-repair-options-grid\">\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-grammar-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"grammarAndFlow\"\n id=\"story-repair-grammar-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Grammar &amp; Flow</span>\n <span class=\"rts-st-checkbox-desc\">Fix typos, punctuation &amp; improve readability across story, slides &amp; entities</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-characters-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"characters\"\n id=\"story-repair-characters-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Characters</span>\n <span class=\"rts-st-checkbox-desc\">Add missing important characters and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-artifacts-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"artifacts\"\n id=\"story-repair-artifacts-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Artifacts</span>\n <span class=\"rts-st-checkbox-desc\">Add missing memorable objects and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-locations-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"locations\"\n id=\"story-repair-locations-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Locations</span>\n <span class=\"rts-st-checkbox-desc\">Add missing story locations and link them to slides</span>\n </span>\n </label>\n </div>\n @if (!hasAtLeastOneOption) {\n <div class=\"rts-storyteller-error\">Please select at least one option to repair.</div>\n }\n </div>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-repair-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-repair-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length || !selectedStory || !hasAtLeastOneOption\"\n id=\"story-repair-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Repairing\u2026\n } @else {\n \uD83D\uDEE0\uFE0F Repair Story\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n", ".rts-st-repair-options-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}@media (max-width: 480px){.rts-st-repair-options-grid{grid-template-columns:1fr}}\n"] }]
2871
3294
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { step: [{
2872
3295
  type: Input
2873
3296
  }], workflow: [{
@@ -2894,6 +3317,7 @@ class WorkflowStepsService {
2894
3317
  { name: 'storyteller-form-step', component: StorytellerFormStepComponent },
2895
3318
  { name: 'storyteller-story-link-step', component: StorytellerStoryLinkStepComponent },
2896
3319
  { name: 'story-translator-form-step', component: StoryTranslatorFormStepComponent },
3320
+ { name: 'story-repair-form-step', component: StoryRepairFormStepComponent },
2897
3321
  ];
2898
3322
  }
2899
3323
  register(widget) {
@@ -3071,29 +3495,47 @@ class MessageComponent {
3071
3495
  this.timeFormatService = timeFormatService;
3072
3496
  this.widgetRef = null;
3073
3497
  this.widgetHasMessageInput = false;
3498
+ this.currentWidgetName = null;
3074
3499
  }
3075
3500
  ngOnInit() { }
3076
3501
  ngOnChanges(changes) {
3077
- // The message instance can be replaced (e.g. images got downsized versions) - forward it to the widget
3078
- if (changes['message'] && !changes['message'].firstChange && this.widgetRef) {
3079
- if (this.widgetHasMessageInput) {
3080
- this.widgetRef.setInput('message', this.message);
3502
+ // The message instance or widget type can be replaced (e.g. stream start -> media widget -> downsized versions)
3503
+ if (changes['message'] && !changes['message'].firstChange) {
3504
+ if (this.widgetHost && this.message?.widget !== this.currentWidgetName) {
3505
+ this.renderWidget();
3506
+ return;
3081
3507
  }
3082
- else {
3083
- this.widgetRef.instance.message = this.message;
3084
- this.widgetRef.changeDetectorRef.markForCheck();
3508
+ if (this.widgetRef) {
3509
+ if (this.widgetHasMessageInput) {
3510
+ this.widgetRef.setInput('message', this.message);
3511
+ }
3512
+ else {
3513
+ this.widgetRef.instance.message = this.message;
3514
+ if (typeof this.widgetRef.instance.ngOnChanges === 'function') {
3515
+ this.widgetRef.instance.ngOnChanges(changes);
3516
+ }
3517
+ }
3518
+ this.widgetRef.changeDetectorRef.detectChanges();
3085
3519
  }
3086
3520
  }
3087
3521
  }
3088
3522
  ngAfterViewInit() {
3523
+ this.renderWidget();
3524
+ }
3525
+ renderWidget() {
3089
3526
  /* eslint-disable */
3090
- if (this.message.widget) {
3527
+ if (!this.widgetHost) {
3528
+ return;
3529
+ }
3530
+ const viewContainerRef = this.widgetHost.viewContainerRef;
3531
+ viewContainerRef.clear();
3532
+ this.widgetRef = null;
3533
+ this.currentWidgetName = this.message?.widget || null;
3534
+ if (this.message?.widget) {
3091
3535
  const widget = this.widgetsService.getWidgetComponentByName(this.message.widget);
3092
3536
  if (!widget) {
3093
3537
  return;
3094
3538
  }
3095
- const viewContainerRef = this.widgetHost.viewContainerRef;
3096
- viewContainerRef.clear();
3097
3539
  const componentToShow = this.componentFactoryResolver.resolveComponentFactory(widget);
3098
3540
  const componentRef = viewContainerRef.createComponent(componentToShow);
3099
3541
  componentRef.instance.message = this.message;
@@ -3106,7 +3548,7 @@ class MessageComponent {
3106
3548
  /* eslint-enable */
3107
3549
  }
3108
3550
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessageComponent, deps: [{ token: MessageWidgetsService }, { token: i0.ComponentFactoryResolver }, { token: TimeFormatHelperService }], target: i0.ɵɵFactoryTarget.Component }); }
3109
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessageComponent, isStandalone: true, selector: "rtsee-message", inputs: { chat: "chat", message: "message", member: "member", messenger: "messenger" }, viewQueries: [{ propertyName: "widgetHost", first: true, predicate: WidgetDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageTimeAndStatusComponent, selector: "rtsee-message-time-and-status", inputs: ["message", "hideStatus", "inChat"] }, { kind: "directive", type: WidgetDirective, selector: "[widgetHost]" }] }); }
3551
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessageComponent, isStandalone: true, selector: "rtsee-message", inputs: { chat: "chat", message: "message", member: "member", messenger: "messenger" }, viewQueries: [{ propertyName: "widgetHost", first: true, predicate: WidgetDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"comment\"\n itemscope\n itemtype=\"https://schema.org/Comment\"\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n itemprop=\"text\"\n data-ugc=\"true\"\n rel=\"ugc\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageTimeAndStatusComponent, selector: "rtsee-message-time-and-status", inputs: ["message", "hideStatus", "inChat"] }, { kind: "directive", type: WidgetDirective, selector: "[widgetHost]" }] }); }
3110
3552
  }
3111
3553
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessageComponent, decorators: [{
3112
3554
  type: Component,
@@ -3115,7 +3557,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
3115
3557
  MessageTimeAndStatusComponent,
3116
3558
  WidgetDirective,
3117
3559
  RatingComponent,
3118
- ], standalone: true, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n" }]
3560
+ ], standalone: true, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"comment\"\n itemscope\n itemtype=\"https://schema.org/Comment\"\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n itemprop=\"text\"\n data-ugc=\"true\"\n rel=\"ugc\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n" }]
3119
3561
  }], ctorParameters: () => [{ type: MessageWidgetsService }, { type: i0.ComponentFactoryResolver }, { type: TimeFormatHelperService }], propDecorators: { chat: [{
3120
3562
  type: Input
3121
3563
  }], message: [{
@@ -3384,11 +3826,11 @@ class MessagesListComponent {
3384
3826
  this.lastGroupedMessage = this.chat.messages[this.chat.messages.length - 1];
3385
3827
  }
3386
3828
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessagesListComponent, deps: [{ token: TimeFormatHelperService }, { token: i2$1.ViewportScroller }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
3387
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessagesListComponent, isStandalone: true, selector: "rtsee-messages-list", inputs: { chat: "chat", messenger: "messenger" }, host: { listeners: { "window:scroll": "onWindowScroll($event)", "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollBlock"], descendants: true }, { propertyName: "contentBlock", first: true, predicate: ["contentBlock"], descendants: true }, { propertyName: "bottomAnchor", first: true, predicate: ["bottomAnchor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div class=\"rts-messenger-message-wrapper\" [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\">\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div class=\"rts-messenger-message-sender-name\">\n <p>{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MessageComponent, selector: "rtsee-message", inputs: ["chat", "message", "member", "messenger"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
3829
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessagesListComponent, isStandalone: true, selector: "rtsee-messages-list", inputs: { chat: "chat", messenger: "messenger" }, host: { listeners: { "window:scroll": "onWindowScroll($event)", "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollBlock"], descendants: true }, { propertyName: "contentBlock", first: true, predicate: ["contentBlock"], descendants: true }, { propertyName: "bottomAnchor", first: true, predicate: ["bottomAnchor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div\n class=\"rts-messenger-message-wrapper\"\n data-ugc=\"true\"\n rel=\"ugc\"\n [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\"\n >\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div\n class=\"rts-messenger-message-sender-name\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n <p itemprop=\"name\">{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MessageComponent, selector: "rtsee-message", inputs: ["chat", "message", "member", "messenger"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
3388
3830
  }
3389
3831
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessagesListComponent, decorators: [{
3390
3832
  type: Component,
3391
- args: [{ selector: 'rtsee-messages-list', imports: [InfiniteScrollDirective, MessageComponent, NgClass], standalone: true, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div class=\"rts-messenger-message-wrapper\" [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\">\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div class=\"rts-messenger-message-sender-name\">\n <p>{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n" }]
3833
+ args: [{ selector: 'rtsee-messages-list', imports: [InfiniteScrollDirective, MessageComponent, NgClass], standalone: true, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div\n class=\"rts-messenger-message-wrapper\"\n data-ugc=\"true\"\n rel=\"ugc\"\n [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\"\n >\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div\n class=\"rts-messenger-message-sender-name\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n <p itemprop=\"name\">{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n" }]
3392
3834
  }], ctorParameters: () => [{ type: TimeFormatHelperService }, { type: i2$1.ViewportScroller }, { type: Document, decorators: [{
3393
3835
  type: Inject,
3394
3836
  args: [DOCUMENT]
@@ -5210,8 +5652,9 @@ class StoryElementsSectionComponent {
5210
5652
  if (this._illustrator) {
5211
5653
  this._illustrator.off('changed', this.onIllustratorChanged);
5212
5654
  }
5213
- for (const [requestId, listener] of this.activeGenerationListeners.entries()) {
5214
- window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, listener);
5655
+ for (const [, listeners] of this.activeGenerationListeners.entries()) {
5656
+ window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, listeners.succeed);
5657
+ window.removeEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, listeners.completed);
5215
5658
  }
5216
5659
  this.activeGenerationListeners.clear();
5217
5660
  }
@@ -5260,15 +5703,29 @@ class StoryElementsSectionComponent {
5260
5703
  this.batchMode = false;
5261
5704
  this.selectedItemIds.clear();
5262
5705
  this.batchAdditionalPrompt = '';
5263
- this.cdr.markForCheck();
5264
5706
  for (const item of selectedItems) {
5265
- const requestId = RTSeeCore.uuidv4();
5266
5707
  this.generatingItemIds.add(item.id);
5267
- const listener = async (e) => {
5708
+ }
5709
+ this.cdr.markForCheck();
5710
+ const batchSpacingMs = 1200;
5711
+ for (let i = 0; i < selectedItems.length; i++) {
5712
+ const item = selectedItems[i];
5713
+ if (i > 0) {
5714
+ await new Promise((resolve) => setTimeout(resolve, batchSpacingMs));
5715
+ }
5716
+ const requestId = RTSeeCore.uuidv4();
5717
+ const cleanupListeners = () => {
5718
+ const entry = this.activeGenerationListeners.get(requestId);
5719
+ if (entry) {
5720
+ window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, entry.succeed);
5721
+ window.removeEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, entry.completed);
5722
+ this.activeGenerationListeners.delete(requestId);
5723
+ }
5724
+ };
5725
+ const succeedListener = async (e) => {
5268
5726
  const customEvent = e;
5269
5727
  if (customEvent.detail?.requestId === requestId && customEvent.detail?.imageUrl) {
5270
- window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, listener);
5271
- this.activeGenerationListeners.delete(requestId);
5728
+ cleanupListeners();
5272
5729
  this.generatingItemIds.delete(item.id);
5273
5730
  const cleanUrl = sanitizeImageUrl(customEvent.detail.imageUrl);
5274
5731
  try {
@@ -5293,8 +5750,20 @@ class StoryElementsSectionComponent {
5293
5750
  }
5294
5751
  }
5295
5752
  };
5296
- window.addEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, listener);
5297
- this.activeGenerationListeners.set(requestId, listener);
5753
+ const completedListener = (e) => {
5754
+ const customEvent = e;
5755
+ if (customEvent.detail?.requestId === requestId && customEvent.detail?.success === false) {
5756
+ cleanupListeners();
5757
+ this.generatingItemIds.delete(item.id);
5758
+ this.cdr.markForCheck();
5759
+ }
5760
+ };
5761
+ window.addEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, succeedListener);
5762
+ window.addEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, completedListener);
5763
+ this.activeGenerationListeners.set(requestId, {
5764
+ succeed: succeedListener,
5765
+ completed: completedListener,
5766
+ });
5298
5767
  const promptParts = [];
5299
5768
  promptParts.push(`${this.editor.label}: ${item.name || ''}`);
5300
5769
  if (item.visualDescription) {
@@ -5319,7 +5788,7 @@ class StoryElementsSectionComponent {
5319
5788
  chatId: this.illustrator?.activeChatId || undefined,
5320
5789
  agentId: this.illustrator?.activeAgentId || '',
5321
5790
  prompt: entityPrompt,
5322
- config: { ...config },
5791
+ config: { ...config, numberOfImages: 1 },
5323
5792
  contextImages: [],
5324
5793
  requestId,
5325
5794
  };
@@ -6084,11 +6553,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
6084
6553
 
6085
6554
  class RtseeEntityCommentsComponent {
6086
6555
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeEntityCommentsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6087
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeEntityCommentsComponent, isStandalone: true, selector: "rtsee-entity-comments", inputs: { messenger: "messenger", chat: "chat", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-entity-comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n", dependencies: [{ kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }] }); }
6556
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeEntityCommentsComponent, isStandalone: true, selector: "rtsee-entity-comments", inputs: { messenger: "messenger", chat: "chat", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-entity-comments\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n", dependencies: [{ kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }] }); }
6088
6557
  }
6089
6558
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeEntityCommentsComponent, decorators: [{
6090
6559
  type: Component,
6091
- args: [{ selector: 'rtsee-entity-comments', imports: [ChatComponent], template: "<div class=\"rtsee-entity-comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n" }]
6560
+ args: [{ selector: 'rtsee-entity-comments', imports: [ChatComponent], template: "<div class=\"rtsee-entity-comments\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n" }]
6092
6561
  }], propDecorators: { messenger: [{
6093
6562
  type: Input
6094
6563
  }], chat: [{
@@ -6175,11 +6644,11 @@ class RateItemComponent {
6175
6644
  return config ? config.name : '';
6176
6645
  }
6177
6646
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RateItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6178
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RateItemComponent, isStandalone: true, selector: "rtsee-rate-item", inputs: { group: "group", rater: "rater", showActions: "showActions" }, outputs: { edit: "edit", delete: "delete" }, ngImport: i0, template: "<div class=\"rtsee-rates-group-item\">\n <div class=\"rtsee-rates-group-header\">\n <div class=\"rtsee-rates-group-user-info\">\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span class=\"rtsee-rates-group-date\">{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: RatingComponent, selector: "rtsee-rating", inputs: ["config", "rate"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
6647
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RateItemComponent, isStandalone: true, selector: "rtsee-rate-item", inputs: { group: "group", rater: "rater", showActions: "showActions" }, outputs: { edit: "edit", delete: "delete" }, ngImport: i0, template: "<div\n class=\"rtsee-rates-group-item\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"review\"\n itemscope\n itemtype=\"https://schema.org/Review\"\n>\n <div class=\"rtsee-rates-group-header\">\n <div\n class=\"rtsee-rates-group-user-info\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n itemprop=\"image\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\" itemprop=\"name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span\n class=\"rtsee-rates-group-date\"\n itemprop=\"datePublished\"\n [attr.content]=\"group.createdAt\"\n >{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\" itemprop=\"reviewBody\" data-ugc=\"true\" rel=\"ugc\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: RatingComponent, selector: "rtsee-rating", inputs: ["config", "rate"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
6179
6648
  }
6180
6649
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RateItemComponent, decorators: [{
6181
6650
  type: Component,
6182
- args: [{ selector: 'rtsee-rate-item', imports: [RatingComponent, DatePipe, Button], template: "<div class=\"rtsee-rates-group-item\">\n <div class=\"rtsee-rates-group-header\">\n <div class=\"rtsee-rates-group-user-info\">\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span class=\"rtsee-rates-group-date\">{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n" }]
6651
+ args: [{ selector: 'rtsee-rate-item', imports: [RatingComponent, DatePipe, Button], template: "<div\n class=\"rtsee-rates-group-item\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"review\"\n itemscope\n itemtype=\"https://schema.org/Review\"\n>\n <div class=\"rtsee-rates-group-header\">\n <div\n class=\"rtsee-rates-group-user-info\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n itemprop=\"image\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\" itemprop=\"name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span\n class=\"rtsee-rates-group-date\"\n itemprop=\"datePublished\"\n [attr.content]=\"group.createdAt\"\n >{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\" itemprop=\"reviewBody\" data-ugc=\"true\" rel=\"ugc\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n" }]
6183
6652
  }], propDecorators: { group: [{
6184
6653
  type: Input
6185
6654
  }], rater: [{
@@ -6296,11 +6765,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
6296
6765
 
6297
6766
  class RatingSectionComponent {
6298
6767
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6299
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: RatingSectionComponent, isStandalone: true, selector: "rtsee-rating-section", inputs: { rater: "rater", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-rating-section\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n", dependencies: [{ kind: "component", type: RaterComponent, selector: "rtsee-rater", inputs: ["entity", "rater"] }, { kind: "component", type: RatesListComponent, selector: "rtsee-rates-list", inputs: ["rater", "entity"] }] }); }
6768
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: RatingSectionComponent, isStandalone: true, selector: "rtsee-rating-section", inputs: { rater: "rater", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-rating-section\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User ratings and reviews\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n", dependencies: [{ kind: "component", type: RaterComponent, selector: "rtsee-rater", inputs: ["entity", "rater"] }, { kind: "component", type: RatesListComponent, selector: "rtsee-rates-list", inputs: ["rater", "entity"] }] }); }
6300
6769
  }
6301
6770
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingSectionComponent, decorators: [{
6302
6771
  type: Component,
6303
- args: [{ selector: 'rtsee-rating-section', imports: [RaterComponent, RatesListComponent], template: "<div class=\"rtsee-rating-section\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n" }]
6772
+ args: [{ selector: 'rtsee-rating-section', imports: [RaterComponent, RatesListComponent], template: "<div class=\"rtsee-rating-section\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User ratings and reviews\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n" }]
6304
6773
  }], propDecorators: { rater: [{
6305
6774
  type: Input
6306
6775
  }], entity: [{
@@ -6539,11 +7008,11 @@ class StoryDetailsComponent {
6539
7008
  return stars;
6540
7009
  }
6541
7010
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6542
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryDetailsComponent, isStandalone: true, selector: "rtsee-story-details", inputs: { story: "story", presentation: "presentation", messenger: "messenger" }, ngImport: i0, template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/CreativeWork\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div class=\"rtsee-story-details-cover-rating\">\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span>&nbsp;</span>\n <span>{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }, { kind: "component", type: RtseeEntityPreviewComponent, selector: "rtsee-entity-preview", inputs: ["entity", "messenger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: StoryElementThumbnailComponent, selector: "rtsee-story-element-thumbnail", inputs: ["name", "description", "imageUrl", "itemProp", "schemaType", "horizontal", "showMoreLabel", "showLessLabel"] }, { kind: "component", type: StorySlidesPreviewComponent, selector: "rtsee-story-slides-preview", inputs: ["story", "slidesLabel", "minuteLabel", "count"] }] }); }
7011
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryDetailsComponent, isStandalone: true, selector: "rtsee-story-details", inputs: { story: "story", presentation: "presentation", messenger: "messenger" }, ngImport: i0, template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/ShortStory\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n @if (story.languageKey) {\n <meta itemprop=\"inLanguage\" [attr.content]=\"story.languageKey === 'ua' ? 'uk' : 'en'\" />\n }\n @if (story.totalSlides) {\n <meta itemprop=\"numberOfPages\" [attr.content]=\"story.totalSlides\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div\n class=\"rtsee-story-details-cover-rating\"\n itemprop=\"aggregateRating\"\n itemscope\n itemtype=\"https://schema.org/AggregateRating\"\n >\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\" itemprop=\"ratingValue\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <meta itemprop=\"ratingCount\" [attr.content]=\"story.ratesCount\" />\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span>&nbsp;</span>\n <span itemprop=\"reviewCount\">{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"backstory\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"teaches\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }, { kind: "component", type: RtseeEntityPreviewComponent, selector: "rtsee-entity-preview", inputs: ["entity", "messenger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: StoryElementThumbnailComponent, selector: "rtsee-story-element-thumbnail", inputs: ["name", "description", "imageUrl", "itemProp", "schemaType", "horizontal", "showMoreLabel", "showLessLabel"] }, { kind: "component", type: StorySlidesPreviewComponent, selector: "rtsee-story-slides-preview", inputs: ["story", "slidesLabel", "minuteLabel", "count"] }] }); }
6543
7012
  }
6544
7013
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryDetailsComponent, decorators: [{
6545
7014
  type: Component,
6546
- args: [{ selector: 'rtsee-story-details', imports: [Chip, Tag, Button, ChatComponent, RtseeEntityPreviewComponent, RouterLink, StoryElementThumbnailComponent, StorySlidesPreviewComponent], template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/CreativeWork\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div class=\"rtsee-story-details-cover-rating\">\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span>&nbsp;</span>\n <span>{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n" }]
7015
+ args: [{ selector: 'rtsee-story-details', imports: [Chip, Tag, Button, ChatComponent, RtseeEntityPreviewComponent, RouterLink, StoryElementThumbnailComponent, StorySlidesPreviewComponent], template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/ShortStory\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n @if (story.languageKey) {\n <meta itemprop=\"inLanguage\" [attr.content]=\"story.languageKey === 'ua' ? 'uk' : 'en'\" />\n }\n @if (story.totalSlides) {\n <meta itemprop=\"numberOfPages\" [attr.content]=\"story.totalSlides\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div\n class=\"rtsee-story-details-cover-rating\"\n itemprop=\"aggregateRating\"\n itemscope\n itemtype=\"https://schema.org/AggregateRating\"\n >\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\" itemprop=\"ratingValue\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <meta itemprop=\"ratingCount\" [attr.content]=\"story.ratesCount\" />\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span>&nbsp;</span>\n <span itemprop=\"reviewCount\">{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"backstory\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"teaches\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n" }]
6547
7016
  }], propDecorators: { story: [{
6548
7017
  type: Input
6549
7018
  }], presentation: [{
@@ -6623,7 +7092,7 @@ class RtseeNavComponent {
6623
7092
  return false;
6624
7093
  }
6625
7094
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeNavComponent, deps: [{ token: RTSeeAuthService }], target: i0.ɵɵFactoryTarget.Component }); }
6626
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeNavComponent, isStandalone: true, selector: "rtsee-nav", inputs: { config: "config", rtsee: "rtsee" }, ngImport: i0, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "component", type: Image, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "appendTo"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
7095
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeNavComponent, isStandalone: true, selector: "rtsee-nav", inputs: { config: "config", rtsee: "rtsee" }, ngImport: i0, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "component", type: Image$1, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "appendTo"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
6627
7096
  }
6628
7097
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeNavComponent, decorators: [{
6629
7098
  type: Component,
@@ -6632,7 +7101,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
6632
7101
  RouterLinkActive,
6633
7102
  NgClass,
6634
7103
  Avatar,
6635
- Image,
7104
+ Image$1,
6636
7105
  Divider,
6637
7106
  Tooltip,
6638
7107
  ], standalone: true, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n" }]