@rtsee/ngx 0.0.116 → 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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { OnInit, AfterViewInit, ElementRef, EventEmitter, OnDestroy, ChangeDetectorRef, OutputEmitterRef, OnChanges, SimpleChanges, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
2
+ import { OnInit, AfterViewInit, ElementRef, EventEmitter, OnDestroy, ChangeDetectorRef, OutputEmitterRef, OnChanges, SimpleChanges, ViewContainerRef, ComponentFactoryResolver, DoCheck } from '@angular/core';
3
3
  import { RTSeeConference, RTSeePeerConnection } from '@rtsee/conference';
4
4
  import { RTSeeMessenger, RTSeeMessengerSearch, RTSeeMessage, RTSeeChat, RTSeeChatMember, RTSeeMentionAutocomplete, RTSeeWorkflowAutocomplete, OzzyClientTask } from '@rtsee/messenger';
5
5
  import { IPeer, RTSeeTextLabelKeys, IRTSeeCall } from '@rtsee/core';
@@ -17,6 +17,7 @@ import * as i44 from '@angular/forms';
17
17
  import { FormGroup, FormBuilder, FormControl, FormArray } from '@angular/forms';
18
18
  import * as i43 from '@angular/common';
19
19
  import { ViewportScroller } from '@angular/common';
20
+ import Swiper from 'swiper';
20
21
  import * as i45 from 'ngx-autosize';
21
22
  import * as i46 from 'ngx-infinite-scroll';
22
23
  import * as i48 from 'ngx-captcha';
@@ -727,10 +728,12 @@ declare class MessageComponent implements OnInit, AfterViewInit, OnChanges {
727
728
  widgetHost: WidgetDirective;
728
729
  private widgetRef;
729
730
  private widgetHasMessageInput;
731
+ private currentWidgetName;
730
732
  constructor(widgetsService: MessageWidgetsService, componentFactoryResolver: ComponentFactoryResolver, timeFormatService: TimeFormatHelperService);
731
733
  ngOnInit(): void;
732
734
  ngOnChanges(changes: SimpleChanges): void;
733
735
  ngAfterViewInit(): void;
736
+ private renderWidget;
734
737
  static ɵfac: i0.ɵɵFactoryDeclaration<MessageComponent, never>;
735
738
  static ɵcmp: i0.ɵɵComponentDeclaration<MessageComponent, "rtsee-message", never, { "chat": { "alias": "chat"; "required": false; }; "message": { "alias": "message"; "required": false; }; "member": { "alias": "member"; "required": false; }; "messenger": { "alias": "messenger"; "required": false; }; }, {}, never, never, true, never>;
736
739
  }
@@ -937,14 +940,41 @@ declare class SearchComponent implements OnInit, OnDestroy {
937
940
  static ɵcmp: i0.ɵɵComponentDeclaration<SearchComponent, "rtsee-search", never, { "search": { "alias": "search"; "required": false; }; }, {}, never, never, true, never>;
938
941
  }
939
942
 
940
- declare class StoryPlayerComponent implements OnInit, AfterViewInit {
943
+ /** Data passed by Swiper's Virtual module to `renderExternal` */
944
+ interface IVirtualSlidesData {
945
+ offset: number;
946
+ from: number;
947
+ to: number;
948
+ slides: number[];
949
+ }
950
+ /**
951
+ * Story slides player.
952
+ *
953
+ * Uses Swiper's Virtual module with `renderExternal`, so Angular only renders the few
954
+ * slides around the active one (Safari crashed when animating 20+ card slides at once).
955
+ * Swiper is aware of ALL the story slides (1..totalSlides) from the start, while the
956
+ * slide contents are lazy loaded by the story; slides not loaded yet render a placeholder.
957
+ */
958
+ declare class StoryPlayerComponent implements OnInit, AfterViewInit, DoCheck, OnDestroy {
959
+ private cdr;
941
960
  story: RTSeeStory;
942
961
  settings: RTSeePresentationSettings;
943
962
  presentation: RTSeePresentation;
944
963
  swiperEl: ElementRef<HTMLElement>;
945
- constructor();
964
+ swiper: Swiper | null;
965
+ /** slide numbers currently rendered by the virtual swiper */
966
+ virtualData: IVirtualSlidesData;
967
+ constructor(cdr: ChangeDetectorRef);
946
968
  ngOnInit(): void;
947
969
  ngAfterViewInit(): void;
970
+ /** grows the virtual slides list when the slides count becomes known / changes */
971
+ ngDoCheck(): void;
972
+ ngOnDestroy(): void;
973
+ getLoadedSlide(slideNumber: number): RTSeeStorySlide | null;
974
+ private renderVirtualSlides;
975
+ private getSlidesCount;
976
+ /** virtual slides are just the slide numbers: 1..N */
977
+ private getVirtualSlides;
948
978
  static ɵfac: i0.ɵɵFactoryDeclaration<StoryPlayerComponent, never>;
949
979
  static ɵcmp: i0.ɵɵComponentDeclaration<StoryPlayerComponent, "rtsee-story-player", never, { "story": { "alias": "story"; "required": false; }; "settings": { "alias": "settings"; "required": false; }; "presentation": { "alias": "presentation"; "required": false; }; }, {}, never, never, true, never>;
950
980
  }
@@ -9,5 +9,7 @@
9
9
  @import "./settings";
10
10
  @import "./join-call";
11
11
  @import "./story-details";
12
+ @import "./story-element-thumbnail";
13
+ @import "./story-slides-preview";
12
14
  @import "./interactive-story-editor";
13
15
  @import "./illustrator";
@@ -23,7 +23,33 @@
23
23
  height: $presentation-dashboard-header-height;
24
24
  top: - $presentation-dashboard-header-height;
25
25
  z-index: 300;
26
- background-color: #ffffff;
26
+ // light reading theme (default)
27
+ background-color: rgba($rts-reading-light-bg, 0.92);
28
+ color: $rts-reading-light-text;
29
+ border-bottom: 1px solid rgba(0, 0, 0, 0.06);
30
+ backdrop-filter: blur(12px);
31
+ transition:
32
+ top 0.5s ease-in-out,
33
+ background-color 0.3s ease,
34
+ color 0.3s ease,
35
+ border-color 0.3s ease;
36
+
37
+ // header button tokens (light)
38
+ --rts-reading-header-btn-bg: rgba(0, 0, 0, 0.05);
39
+ --rts-reading-header-btn-bg-hover: rgba(0, 0, 0, 0.1);
40
+ --rts-reading-header-muted: #{$rts-reading-light-muted};
41
+ --rts-reading-header-progress-track: rgba(0, 0, 0, 0.06);
42
+ }
43
+
44
+ &.rtsee-presentation-header-convertable.rtsee-presentation-header-theme-dark {
45
+ background-color: rgba($rts-reading-dark-bg, 0.92);
46
+ color: $rts-reading-dark-text;
47
+ border-bottom-color: rgba(255, 255, 255, 0.06);
48
+
49
+ --rts-reading-header-btn-bg: rgba(255, 255, 255, 0.06);
50
+ --rts-reading-header-btn-bg-hover: rgba(255, 255, 255, 0.12);
51
+ --rts-reading-header-muted: #{$rts-reading-dark-muted};
52
+ --rts-reading-header-progress-track: rgba(255, 255, 255, 0.06);
27
53
  }
28
54
 
29
55
  &.rtsee-presentation-header-visible {
@@ -75,52 +101,133 @@
75
101
 
76
102
  .rtsee-presentation-header-active-story-info {
77
103
  position: relative;
78
- padding: 0 $presentation-dashboard-header-height;
104
+ display: flex;
105
+ align-items: center;
106
+ gap: $rts-offset-sm;
107
+ height: $presentation-dashboard-header-height;
108
+ padding: 0 $rts-offset-sm;
79
109
 
80
- .rtsee-presentation-header-active-story-info-close {
81
- position: absolute;
82
- display: flex;
110
+ // round icon buttons (back / settings)
111
+ .rtsee-presentation-header-icon-btn {
112
+ flex-shrink: 0;
113
+ display: inline-flex;
83
114
  align-items: center;
84
115
  justify-content: center;
85
- top: 0;
86
- left: 0;
87
- height: $presentation-dashboard-header-height;
88
- width: $presentation-dashboard-header-height;
116
+ width: 38px;
117
+ height: 38px;
118
+ padding: 0;
119
+ border: none;
120
+ border-radius: 50%;
121
+ background: var(--rts-reading-header-btn-bg);
122
+ color: inherit;
123
+ font: inherit;
89
124
  cursor: pointer;
90
- color: $rts-rates-bg-form-start;
125
+ transition:
126
+ background-color 0.2s ease,
127
+ transform 0.2s ease;
128
+
129
+ &:hover {
130
+ background: var(--rts-reading-header-btn-bg-hover);
131
+ }
132
+
133
+ &:active {
134
+ transform: scale(0.94);
135
+ }
136
+
137
+ &:focus-visible {
138
+ outline: 2px solid $rts-rates-accent-purple;
139
+ outline-offset: 2px;
140
+ }
91
141
 
92
- .rtsee-presentation-header-active-story-info-close-icon {
93
- font-size: 1.5rem
142
+ .pi {
143
+ font-size: 1.05rem;
94
144
  }
95
145
  }
96
146
 
97
- .rtsee-presentation-header-active-story-info-details {
98
- padding: 5px 0;
147
+ .rtsee-presentation-header-active-story-info-close:hover .pi {
148
+ transform: translateX(-2px);
149
+ }
150
+
151
+ .rtsee-presentation-header-active-story-info-close .pi {
152
+ transition: transform 0.2s ease;
153
+ }
154
+
155
+ // "Aa" reading settings glyph
156
+ .rtsee-presentation-header-settings-glyph {
157
+ display: inline-flex;
158
+ align-items: baseline;
159
+ font-family: Georgia, "Times New Roman", serif;
160
+ font-weight: 700;
161
+ line-height: 1;
162
+ letter-spacing: -0.02em;
99
163
 
100
- .rtsee-presentation-header-active-story-name {
101
- white-space: nowrap;
102
- overflow: hidden;
103
- text-overflow: ellipsis;
104
- max-width: 100%;
164
+ .rtsee-presentation-header-settings-glyph-big {
165
+ font-size: 1.15rem;
166
+ }
167
+
168
+ .rtsee-presentation-header-settings-glyph-small {
169
+ font-size: 0.85rem;
105
170
  }
106
171
  }
107
172
 
108
- .rtsee-presentation-header-active-story-info-settings {
109
- position: absolute;
173
+ .rtsee-presentation-header-active-story-info-details {
174
+ flex: 1;
175
+ min-width: 0;
110
176
  display: flex;
111
177
  align-items: center;
112
- justify-content: center;
113
- width: $presentation-dashboard-header-height;
114
- height: $presentation-dashboard-header-height;
178
+ gap: ($rts-offset-sm + $rts-offset-xsm);
179
+ }
180
+
181
+ .rtsee-presentation-header-active-story-cover {
182
+ flex-shrink: 0;
183
+ width: 34px;
184
+ height: 34px;
185
+ border-radius: 8px;
186
+ object-fit: cover;
187
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
188
+ }
189
+
190
+ .rtsee-presentation-header-active-story-text {
191
+ display: flex;
192
+ flex-direction: column;
193
+ min-width: 0;
194
+ line-height: 1.2;
195
+ }
196
+
197
+ .rtsee-presentation-header-active-story-name {
198
+ font-size: 0.95rem;
199
+ font-weight: 600;
200
+ white-space: nowrap;
201
+ overflow: hidden;
202
+ text-overflow: ellipsis;
203
+ }
204
+
205
+ .rtsee-presentation-header-active-story-progress-label {
206
+ font-size: 0.75rem;
207
+ font-weight: 500;
208
+ color: var(--rts-reading-header-muted);
209
+ font-variant-numeric: tabular-nums;
210
+ }
211
+
212
+ // thin reading progress bar along the bottom edge
213
+ .rtsee-presentation-header-active-story-progress {
214
+ position: absolute;
215
+ left: 0;
115
216
  right: 0;
116
- top: 0;
117
- cursor: pointer;
217
+ bottom: -1px;
218
+ height: 2px;
219
+ background: var(--rts-reading-header-progress-track);
220
+ overflow: hidden;
118
221
 
119
- .rtsee-presentation-header-active-story-info-settings-icon {
120
- font-size: 1.8rem;
121
- padding: 7px;
122
- background-color: rgba(0, 0, 0, 0.06);
123
- border-radius: 50%;
222
+ .rtsee-presentation-header-active-story-progress-bar {
223
+ height: 100%;
224
+ background: linear-gradient(
225
+ 90deg,
226
+ $rts-rates-accent-purple 0%,
227
+ $rts-rates-accent-purple-light 100%
228
+ );
229
+ border-radius: 0 2px 2px 0;
230
+ transition: width 0.4s ease;
124
231
  }
125
232
  }
126
233
  }
@@ -65,6 +65,43 @@
65
65
  }
66
66
  }
67
67
 
68
+ .rtsee-presentation-reading-theme-settings {
69
+ .rtsee-presentation-reading-theme-toggle {
70
+ display: flex;
71
+ margin-bottom: $rts-offset-md;
72
+
73
+ .p-togglebutton {
74
+ flex: 1;
75
+ }
76
+
77
+ .p-togglebutton-content {
78
+ display: inline-flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ gap: $rts-offset-sm;
82
+ width: 100%;
83
+ }
84
+ }
85
+
86
+ .rtsee-presentation-reading-theme-example {
87
+ padding: $rts-offset-md;
88
+ border-radius: 10px;
89
+ line-height: 1.6;
90
+ background-color: $rts-reading-light-bg;
91
+ color: $rts-reading-light-text;
92
+ border: 1px solid rgba(0, 0, 0, 0.08);
93
+ transition:
94
+ background-color 0.3s ease,
95
+ color 0.3s ease;
96
+
97
+ &.rtsee-presentation-reading-theme-example-dark {
98
+ background-color: $rts-reading-dark-bg;
99
+ color: $rts-reading-dark-text;
100
+ border-color: rgba(255, 255, 255, 0.06);
101
+ }
102
+ }
103
+ }
104
+
68
105
  @media screen and (min-width: $rts-break-md) {
69
106
  position: absolute;
70
107
  }
@@ -227,43 +227,154 @@
227
227
  }
228
228
  }
229
229
 
230
- /* ── HERO ACTIONS (buttons) ────────────────────────────────── */
230
+ /* ── READING PANEL (slides preview + start reading CTA) ─────── */
231
231
 
232
- .rtsee-story-details-cover-actions {
232
+ .rtsee-story-details-reading-panel {
233
+ position: relative;
234
+ z-index: 3;
233
235
  display: flex;
236
+ flex-direction: column;
234
237
  align-items: stretch;
235
- margin-top: -$rts-offset-md;
236
- padding-bottom: $rts-offset-xl;
238
+ gap: ($rts-offset-md + $rts-offset-xsm);
239
+ margin: (-$rts-offset-lg) 0 $rts-offset-xl;
240
+ padding: ($rts-offset-md + $rts-offset-xsm);
241
+ border-radius: 20px;
242
+ border: 1px solid rgba($rts-rates-accent-purple, 0.25);
243
+ background:
244
+ radial-gradient(
245
+ 120% 140% at 0% 0%,
246
+ rgba($rts-rates-accent-purple, 0.18) 0%,
247
+ rgba($rts-rates-accent-purple, 0) 60%
248
+ ),
249
+ linear-gradient(
250
+ 135deg,
251
+ $rts-rates-bg-card-start 0%,
252
+ $rts-rates-bg-card-end 100%
253
+ );
254
+ backdrop-filter: blur(14px);
255
+ box-shadow:
256
+ 0 12px 40px rgba(0, 0, 0, 0.35),
257
+ 0 0 0 1px rgba(255, 255, 255, 0.02) inset;
258
+ animation: rtseeCardSlideUp 0.6s ease-out both;
237
259
 
238
- // Mobile-first default
239
- flex-direction: column;
240
- gap: $rts-offset-sm;
241
- width: 100%;
260
+ // fan the preview circles out when the panel is hovered
261
+ &:hover .rtsee-story-slides-preview-circle {
262
+ &:nth-child(1) { transform: translateX(-4px) rotate(-8deg); }
263
+ &:nth-child(2) { transform: translateY(-3px); }
264
+ &:nth-child(3) { transform: translateX(4px) rotate(8deg); }
265
+ }
242
266
 
243
- /* Override primeng button defaults to look premium dark theme */
244
- ::v-deep .p-button {
245
- border-radius: 8px;
246
- font-weight: 600;
247
- padding: 12px 24px;
248
- transition:
249
- transform 0.2s ease,
250
- box-shadow 0.2s ease;
251
- width: 100%;
267
+ rtsee-story-slides-preview {
268
+ display: block;
252
269
  }
253
270
 
254
- .rtsee-story-details-start-reading ::v-deep .p-button {
255
- background: linear-gradient(135deg, $rts-rates-accent-purple 0%, $rts-rates-accent-purple-light 100%);
256
- border: none;
257
- box-shadow: 0 4px 16px rgba($rts-rates-accent-purple, 0.3);
271
+ /* ── Start reading CTA ── */
272
+ .rtsee-story-details-start-reading.rts-action-button {
273
+ display: block;
274
+ width: 100%;
258
275
 
259
- &:hover {
260
- transform: translateY(-2px);
261
- box-shadow: 0 6px 20px rgba($rts-rates-accent-purple, 0.4);
276
+ .p-button {
277
+ position: relative;
278
+ overflow: hidden;
279
+ width: 100%;
280
+ min-height: 58px;
281
+ justify-content: center;
282
+ gap: ($rts-offset-sm + $rts-offset-xsm);
283
+ padding: $rts-offset-md $rts-offset-lg;
284
+ border: none;
285
+ border-radius: 14px;
286
+ font-size: 1.12rem;
287
+ font-weight: 700;
288
+ letter-spacing: 0.01em;
289
+ color: #fff;
290
+ background: linear-gradient(
291
+ 135deg,
292
+ $rts-rates-accent-purple 0%,
293
+ $rts-rates-accent-purple-light 100%
294
+ );
295
+ box-shadow:
296
+ 0 8px 24px rgba($rts-rates-accent-purple, 0.45),
297
+ 0 0 0 1px rgba(255, 255, 255, 0.12) inset;
298
+ animation: rtseeStartReadingGlow 2.8s ease-in-out infinite;
299
+ transition:
300
+ transform 0.2s ease,
301
+ box-shadow 0.2s ease,
302
+ filter 0.2s ease;
303
+
304
+ .p-button-icon {
305
+ font-size: 1.15rem;
306
+ }
307
+
308
+ // soft light sweep across the button
309
+ &::after {
310
+ content: "";
311
+ position: absolute;
312
+ top: 0;
313
+ left: -60%;
314
+ width: 40%;
315
+ height: 100%;
316
+ background: linear-gradient(
317
+ 100deg,
318
+ rgba(255, 255, 255, 0) 0%,
319
+ rgba(255, 255, 255, 0.28) 50%,
320
+ rgba(255, 255, 255, 0) 100%
321
+ );
322
+ transform: skewX(-20deg);
323
+ animation: rtseeStartReadingShine 3.6s ease-in-out infinite;
324
+ pointer-events: none;
325
+ }
326
+
327
+ &:hover {
328
+ animation: none;
329
+ transform: translateY(-2px);
330
+ filter: brightness(1.06);
331
+ box-shadow:
332
+ 0 12px 30px rgba($rts-rates-accent-purple, 0.55),
333
+ 0 0 0 1px rgba(255, 255, 255, 0.18) inset;
334
+ }
335
+
336
+ &:active {
337
+ transform: translateY(0) scale(0.99);
338
+ }
339
+
340
+ &:focus-visible {
341
+ outline: 2px solid $rts-rates-accent-purple-light;
342
+ outline-offset: 3px;
343
+ }
262
344
  }
345
+ }
346
+ }
263
347
 
264
- &:active {
265
- transform: translateY(0);
266
- box-shadow: 0 4px 12px rgba($rts-rates-accent-purple, 0.3);
348
+ @keyframes rtseeStartReadingGlow {
349
+ 0%,
350
+ 100% {
351
+ box-shadow:
352
+ 0 8px 24px rgba($rts-rates-accent-purple, 0.4),
353
+ 0 0 0 1px rgba(255, 255, 255, 0.12) inset;
354
+ }
355
+ 50% {
356
+ box-shadow:
357
+ 0 8px 32px rgba($rts-rates-accent-purple, 0.65),
358
+ 0 0 0 1px rgba(255, 255, 255, 0.12) inset;
359
+ }
360
+ }
361
+
362
+ @keyframes rtseeStartReadingShine {
363
+ 0%,
364
+ 60% {
365
+ left: -60%;
366
+ }
367
+ 100% {
368
+ left: 130%;
369
+ }
370
+ }
371
+
372
+ @media (prefers-reduced-motion: reduce) {
373
+ .rtsee-story-details-reading-panel .rtsee-story-details-start-reading .p-button {
374
+ animation: none;
375
+
376
+ &::after {
377
+ display: none;
267
378
  }
268
379
  }
269
380
  }
@@ -351,6 +462,47 @@
351
462
  white-space: pre-line;
352
463
  }
353
464
 
465
+ /* ── STORY ELEMENTS (author / characters / artifacts / places) ── */
466
+
467
+ .rtsee-story-details-elements {
468
+ margin-bottom: $rts-offset-xl;
469
+ }
470
+
471
+ .rtsee-story-details-elements-grid {
472
+ list-style: none;
473
+ margin: 0;
474
+ padding: 0;
475
+ display: grid;
476
+ gap: ($rts-offset-sm + $rts-offset-xsm);
477
+ // compact row thumbnails: single column on phones, auto-filled columns on wider screens
478
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
479
+ // an expanded card shouldn't stretch its row neighbours
480
+ align-items: start;
481
+ }
482
+
483
+ .rtsee-story-details-elements-item {
484
+ min-width: 0;
485
+
486
+ rtsee-story-element-thumbnail {
487
+ display: block;
488
+ }
489
+
490
+ // stagger card entrance
491
+ @for $i from 1 through 8 {
492
+ &:nth-child(#{$i}) .rtsee-story-element-thumbnail {
493
+ animation-delay: #{$i * 0.06}s;
494
+ }
495
+ }
496
+ }
497
+
498
+ .rtsee-story-details-elements-featured {
499
+ max-width: 560px;
500
+
501
+ rtsee-story-element-thumbnail {
502
+ display: block;
503
+ }
504
+ }
505
+
354
506
  /* ── COMMENTS SECTION / INTEGRATED LOGIC ─────────────────── */
355
507
 
356
508
  .rtsee-story-details-votes {
@@ -392,15 +544,13 @@
392
544
  gap: $rts-offset-lg;
393
545
  }
394
546
 
395
- .rtsee-story-details-cover-actions {
396
- flex-direction: row;
397
- align-items: center;
547
+ .rtsee-story-details-elements-grid {
398
548
  gap: $rts-offset-md;
399
- width: auto;
549
+ }
400
550
 
401
- ::v-deep .p-button {
402
- width: auto;
403
- }
551
+ .rtsee-story-details-reading-panel {
552
+ max-width: 460px;
553
+ padding: $rts-offset-lg;
404
554
  }
405
555
  }
406
556