@lincyaw/viewer 1.0.0-rc.0 → 1.0.0-rc.2

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.
Files changed (70) hide show
  1. package/README.md +6 -4
  2. package/package.json +20 -8
  3. package/src/client/block.ts +70 -0
  4. package/src/client/code/code-block.ts +54 -0
  5. package/src/client/code/code-editor.ts +73 -0
  6. package/src/client/code/code-view.ts +22 -0
  7. package/src/{highlight.ts → client/code/highlight.ts} +2 -2
  8. package/src/{outputs.ts → client/code/outputs.ts} +23 -36
  9. package/src/client/content-marks.ts +15 -0
  10. package/src/client/element.ts +27 -0
  11. package/src/client/index.ts +40 -0
  12. package/src/client/layout.ts +22 -0
  13. package/src/{markdown.ts → client/markdown/handlers.ts} +22 -116
  14. package/src/client/markdown/hast.ts +20 -0
  15. package/src/client/markdown/layout-handlers.ts +57 -0
  16. package/src/client/markdown/math.ts +10 -0
  17. package/src/client/markdown/mermaid.ts +75 -0
  18. package/src/client/markdown/render.ts +79 -0
  19. package/src/client/markdown/role-mark.ts +9 -0
  20. package/src/client/markdown/tables.ts +49 -0
  21. package/src/client/markdown/tabs.ts +52 -0
  22. package/src/client/markdown/tree-cache.ts +77 -0
  23. package/src/client/operations.ts +9 -0
  24. package/src/client/registry.ts +21 -0
  25. package/src/client/section-context.ts +5 -0
  26. package/src/client/section.ts +30 -0
  27. package/src/client/slidev-compat/click-directives.ts +16 -0
  28. package/src/client/slidev-compat/slide-globals.ts +3 -0
  29. package/src/{style.css → client/style.css} +306 -81
  30. package/src/client/viewer-messages.ts +7 -0
  31. package/src/{plugins.ts → client/viewer-plugins.ts} +3 -2
  32. package/src/client/viewer-state.ts +47 -0
  33. package/src/client/views/actions.ts +52 -0
  34. package/src/client/views/controls.css +44 -0
  35. package/src/client/views/document.ts +12 -0
  36. package/src/client/views/outlets.ts +37 -0
  37. package/src/client/views/overlay.ts +16 -0
  38. package/src/client/views/present.ts +132 -0
  39. package/src/client/views/presenter.ts +76 -0
  40. package/src/client/views/scrolly.ts +4 -0
  41. package/src/client/views/slide.css +8 -0
  42. package/src/client/views/slide.ts +57 -0
  43. package/src/domain/clicks.ts +1 -1
  44. package/src/domain/code-width.ts +11 -0
  45. package/src/domain/document-content.ts +6 -0
  46. package/src/domain/{text.ts → footnotes.ts} +0 -12
  47. package/src/domain/index.ts +5 -4
  48. package/src/domain/live.ts +11 -10
  49. package/src/domain/messages.ts +54 -30
  50. package/src/domain/origin.ts +17 -32
  51. package/src/domain/outputs.ts +27 -0
  52. package/src/domain/steps.ts +2 -1
  53. package/src/block.ts +0 -122
  54. package/src/cards.ts +0 -130
  55. package/src/clicks.ts +0 -124
  56. package/src/code.ts +0 -235
  57. package/src/context.ts +0 -16
  58. package/src/dark.ts +0 -5
  59. package/src/domain/follow.ts +0 -32
  60. package/src/globals.ts +0 -66
  61. package/src/i18n.ts +0 -7
  62. package/src/index.ts +0 -55
  63. package/src/operations.ts +0 -28
  64. package/src/present.ts +0 -327
  65. package/src/registry.ts +0 -81
  66. package/src/rich.ts +0 -155
  67. package/src/section.ts +0 -209
  68. package/src/viewer.ts +0 -116
  69. package/src/views.ts +0 -101
  70. /package/src/{env.d.ts → client/env.d.ts} +0 -0
@@ -1,21 +1,23 @@
1
+ @import './views/controls.css';
2
+
1
3
  :root {
2
- --pm-c-bg: var(--vp-c-bg, #fff);
3
- --pm-c-bg-soft: var(--vp-c-bg-soft, #f6f6f7);
4
- --pm-c-text: var(--vp-c-text-1, #213547);
5
- --pm-c-text-2: var(--vp-c-text-2, #476582);
6
- --pm-c-border: var(--vp-c-divider, #e2e2e3);
7
- --pm-c-brand: var(--vp-c-brand-1, #3451b2);
8
- --pm-c-danger: var(--vp-c-danger-1, #b8272c);
9
- --pm-c-warning: var(--vp-c-warning-1, #915930);
10
- --pm-code-bg: var(--vp-code-block-bg, #f6f6f7);
11
- --pm-line-highlight: var(--vp-code-line-highlight-color, rgba(142, 150, 170, 0.14));
4
+ --pm-c-bg: var(--pm-color-bg);
5
+ --pm-c-bg-soft: var(--pm-color-sunk);
6
+ --pm-c-text: var(--pm-color-ink);
7
+ --pm-c-text-2: var(--pm-color-muted);
8
+ --pm-c-border: var(--pm-color-line);
9
+ --pm-c-brand: var(--pm-color-accent);
10
+ --pm-c-danger: var(--pm-color-danger);
11
+ --pm-c-warning: var(--pm-color-warn);
12
+ --pm-code-bg: var(--pm-color-code);
13
+ --pm-line-highlight: var(--pm-color-selected);
12
14
  --pm-board-bg: color-mix(in srgb, var(--pm-c-brand) 4%, var(--pm-c-bg));
13
15
  --pm-board-border: var(--pm-c-border);
14
- --pm-scroll-shadow: rgba(0, 0, 0, 0.18);
16
+ --pm-scroll-shadow: color-mix(in srgb, var(--pm-color-shadow) 18%, transparent);
15
17
  }
16
18
 
17
19
  .dark {
18
- --pm-scroll-shadow: rgba(255, 255, 255, 0.16);
20
+ --pm-scroll-shadow: color-mix(in srgb, var(--pm-color-sheen) 16%, transparent);
19
21
  }
20
22
 
21
23
  .pm-hidden,
@@ -27,7 +29,7 @@
27
29
  .pm-block,
28
30
  .pm-block li,
29
31
  [data-pm-click] {
30
- transition: opacity 0.3s;
32
+ transition: opacity var(--pm-duration-slow) var(--pm-ease);
31
33
  }
32
34
 
33
35
  @media (prefers-reduced-motion: reduce) {
@@ -88,7 +90,7 @@
88
90
  .pm-diagnostics {
89
91
  margin: 0.5rem 0;
90
92
  padding: 0.5rem 0.75rem 0.5rem 1.75rem;
91
- border: 1px solid var(--pm-c-danger);
93
+ border: var(--pm-size-hairline) solid var(--pm-c-danger);
92
94
  border-radius: 0.25rem;
93
95
  color: var(--pm-c-danger);
94
96
  font-size: 0.875em;
@@ -97,8 +99,8 @@
97
99
  .pm-board {
98
100
  margin: 1.25rem 0;
99
101
  padding: 0.75rem 1.25rem;
100
- border: 1px solid var(--pm-board-border);
101
- border-left: 4px solid var(--pm-c-brand);
102
+ border: var(--pm-size-hairline) solid var(--pm-board-border);
103
+ border-left: calc(var(--pm-size-stroke) * 2) solid var(--pm-c-brand);
102
104
  border-radius: 0.5rem;
103
105
  background: var(--pm-board-bg);
104
106
  }
@@ -133,7 +135,7 @@
133
135
 
134
136
  .pm-section--scrolly > .pm-stage {
135
137
  position: sticky;
136
- top: calc(var(--vp-nav-height, 0px) + 1rem);
138
+ top: calc(var(--pm-sticky-top, 0rem) + 1rem);
137
139
  margin: 0;
138
140
  padding: 0.75rem;
139
141
  container-type: inline-size;
@@ -146,7 +148,7 @@
146
148
  .pm-step {
147
149
  min-height: 45vh;
148
150
  padding-left: 0.75rem;
149
- border-left: 2px solid var(--pm-c-border);
151
+ border-left: var(--pm-size-stroke) solid var(--pm-c-border);
150
152
  }
151
153
 
152
154
  .pm-step--current {
@@ -168,7 +170,7 @@
168
170
  }
169
171
 
170
172
  .pm-section--scrolly > .pm-stage {
171
- top: var(--vp-nav-height, 0px);
173
+ top: var(--pm-sticky-top, 0rem);
172
174
  z-index: 1;
173
175
  max-height: 50vh;
174
176
  overflow-y: auto;
@@ -191,7 +193,7 @@
191
193
  .pm-code-origin__file,
192
194
  .pm-code-origin__commit,
193
195
  .pm-code-origin__variant {
194
- font-family: var(--vp-font-family-mono, monospace);
196
+ font-family: var(--pm-font-mono);
195
197
  overflow-wrap: anywhere;
196
198
  }
197
199
 
@@ -203,7 +205,7 @@
203
205
  .pm-code-origin__badge {
204
206
  padding: 0 0.4em;
205
207
  border-radius: 0.25rem;
206
- border: 1px solid currentColor;
208
+ border: var(--pm-size-hairline) solid currentColor;
207
209
  color: var(--pm-c-warning);
208
210
  }
209
211
 
@@ -213,20 +215,8 @@
213
215
 
214
216
  .pm-code-block__run {
215
217
  display: flex;
216
- gap: 0.5rem;
218
+ gap: var(--pm-space-1);
217
219
  align-items: center;
218
- font-size: 0.85em;
219
- }
220
-
221
- .pm-code-block__run button {
222
- padding: 0.125rem 0.75rem;
223
- border: 1px solid var(--pm-c-brand);
224
- border-radius: 0.25rem;
225
- color: var(--pm-c-brand);
226
- }
227
-
228
- .pm-code-block__run button:disabled {
229
- opacity: 0.6;
230
220
  }
231
221
 
232
222
  .pm-code-block__hint {
@@ -257,7 +247,7 @@
257
247
 
258
248
  .pm-stage .pm-code pre {
259
249
  --pm-code-pad: 0.75rem;
260
- font-size: clamp(0.65rem, (100cqi - 2 * var(--pm-code-pad) - 2px) / (var(--pm-code-columns, 40) * 0.62), 0.875rem);
250
+ font-size: clamp(0.65rem, (100cqi - 2 * var(--pm-code-pad) - var(--pm-size-stroke)) / (var(--pm-code-columns, 40) * 0.62), 0.875rem);
261
251
  }
262
252
 
263
253
  .pm-view table {
@@ -283,7 +273,7 @@
283
273
  }
284
274
 
285
275
  .pm-code code {
286
- font-family: var(--vp-font-family-mono, monospace);
276
+ font-family: var(--pm-font-mono);
287
277
  }
288
278
 
289
279
  .pm-code .shiki span {
@@ -314,7 +304,7 @@
314
304
  margin: 0.25rem 0;
315
305
  padding: 0.5rem 0.75rem;
316
306
  overflow-x: auto;
317
- border-left: 3px solid var(--pm-c-border);
307
+ border-left: var(--pm-size-rule) solid var(--pm-c-border);
318
308
  background: var(--pm-c-bg-soft);
319
309
  font-size: 0.8125em;
320
310
  }
@@ -368,7 +358,7 @@
368
358
  .pm-admonition {
369
359
  margin: 1rem 0;
370
360
  padding: 0.25rem 1rem;
371
- border-left: 4px solid var(--pm-c-brand);
361
+ border-left: calc(var(--pm-size-stroke) * 2) solid var(--pm-c-brand);
372
362
  border-radius: 0.25rem;
373
363
  background: var(--pm-c-bg-soft);
374
364
  }
@@ -386,11 +376,11 @@
386
376
 
387
377
  .pm-block kbd {
388
378
  padding: 0.05em 0.35em;
389
- border: 1px solid var(--pm-c-border);
390
- border-bottom-width: 2px;
379
+ border: var(--pm-size-hairline) solid var(--pm-c-border);
380
+ border-bottom-width: var(--pm-size-stroke);
391
381
  border-radius: 0.25rem;
392
382
  background: var(--pm-c-bg-soft);
393
- font-family: var(--vp-font-family-mono, monospace);
383
+ font-family: var(--pm-font-mono);
394
384
  font-size: 0.875em;
395
385
  }
396
386
 
@@ -405,7 +395,7 @@
405
395
  .pm-block details {
406
396
  margin: 1rem 0;
407
397
  padding: 0.25rem 1rem;
408
- border: 1px solid var(--pm-c-border);
398
+ border: var(--pm-size-hairline) solid var(--pm-c-border);
409
399
  border-radius: 0.25rem;
410
400
  }
411
401
 
@@ -467,7 +457,7 @@
467
457
  display: flex;
468
458
  flex-direction: column;
469
459
  margin: 1rem 0;
470
- border: 1px solid var(--pm-c-border);
460
+ border: var(--pm-size-hairline) solid var(--pm-c-border);
471
461
  border-radius: 0.5rem;
472
462
  background: var(--pm-c-bg);
473
463
  overflow: hidden;
@@ -488,12 +478,12 @@
488
478
  }
489
479
 
490
480
  .pm-card__header {
491
- border-bottom: 1px solid var(--pm-c-border);
481
+ border-bottom: var(--pm-size-hairline) solid var(--pm-c-border);
492
482
  }
493
483
 
494
484
  .pm-card__footer {
495
485
  margin-top: auto;
496
- border-top: 1px solid var(--pm-c-border);
486
+ border-top: var(--pm-size-hairline) solid var(--pm-c-border);
497
487
  }
498
488
 
499
489
  .pm-card > .pm-card__title {
@@ -536,8 +526,8 @@
536
526
  .pm-block .pm-button {
537
527
  display: inline-block;
538
528
  padding: 0.3em 1em;
539
- border: 1px solid var(--pm-c-brand);
540
- border-radius: 999px;
529
+ border: var(--pm-size-hairline) solid var(--pm-c-brand);
530
+ border-radius: var(--pm-radius-pill);
541
531
  color: var(--pm-c-brand);
542
532
  font-weight: 600;
543
533
  text-decoration: none;
@@ -556,13 +546,13 @@
556
546
  display: flex;
557
547
  flex-wrap: wrap;
558
548
  gap: 0.25rem;
559
- border-bottom: 1px solid var(--pm-c-border);
549
+ border-bottom: var(--pm-size-hairline) solid var(--pm-c-border);
560
550
  }
561
551
 
562
552
  .pm-tabs__tab {
563
553
  margin-bottom: -1px;
564
554
  padding: 0.4rem 0.9rem;
565
- border-bottom: 2px solid transparent;
555
+ border-bottom: var(--pm-size-stroke) solid transparent;
566
556
  color: var(--pm-c-text-2);
567
557
  cursor: pointer;
568
558
  }
@@ -596,7 +586,7 @@
596
586
 
597
587
  .pm-component-missing {
598
588
  padding: 0.5rem 0.75rem;
599
- border: 1px dashed var(--pm-c-border);
589
+ border: var(--pm-size-hairline) dashed var(--pm-c-border);
600
590
  border-radius: 0.25rem;
601
591
  color: var(--pm-c-text-2);
602
592
  font-size: 0.875em;
@@ -604,7 +594,7 @@
604
594
 
605
595
  .pm-boundary-error {
606
596
  padding: 0.5rem 0.75rem;
607
- border: 1px dashed var(--pm-c-danger);
597
+ border: var(--pm-size-hairline) dashed var(--pm-c-danger);
608
598
  border-radius: 0.25rem;
609
599
  color: var(--pm-c-danger);
610
600
  font-size: 0.85em;
@@ -618,7 +608,7 @@ html.pm-presenting {
618
608
  .pm-presenter {
619
609
  position: fixed;
620
610
  inset: 0;
621
- z-index: 1000;
611
+ z-index: var(--pm-z-overlay-view);
622
612
  display: flex;
623
613
  flex-direction: column;
624
614
  background: var(--pm-c-bg);
@@ -646,33 +636,264 @@ html.pm-presenting {
646
636
  .pm-present__slide {
647
637
  position: relative;
648
638
  flex: 1;
639
+ min-height: 0;
640
+ padding: 2vh 2vw;
641
+ }
642
+
643
+ /* A slide: its canvas, scaled as a whole to its box, and the Book layout on it. */
644
+
645
+ .pm-slide-fit {
646
+ position: relative;
649
647
  width: 100%;
648
+ height: 100%;
649
+ overflow: hidden;
650
+ }
651
+
652
+ .pm-slide-fit__canvas {
653
+ position: absolute;
654
+ top: 0;
655
+ left: 0;
656
+ transform-origin: 0 0;
657
+ box-shadow: var(--pm-shadow-page);
658
+ }
659
+
660
+ .pm-slide {
661
+ position: relative;
662
+ box-sizing: border-box;
663
+ display: flex;
664
+ flex-direction: column;
665
+ width: 100%;
666
+ height: 100%;
667
+ padding: 1.9em 3.1em 2.6em;
668
+ overflow: hidden;
669
+ background: var(--pm-color-surface);
670
+ color: var(--pm-color-ink);
671
+ font-family: var(--pm-font-sans);
672
+ font-size: var(--pm-slide-text);
673
+ line-height: 1.6;
674
+ }
675
+
676
+ .pm-slide :is(ul, ol) {
677
+ margin: 0.67em 0;
678
+ padding-inline-start: 1.3em;
679
+ }
680
+
681
+ .pm-slide li::marker {
682
+ color: var(--pm-color-accent);
683
+ }
684
+
685
+ .pm-slide :is(table, th, td) {
686
+ font-size: 0.95em;
687
+ }
688
+
689
+ .pm-slide :is(th, td) {
690
+ padding: 0.3em 0.6em;
691
+ }
692
+
693
+ .pm-slide__chapter {
694
+ display: flex;
695
+ align-items: center;
696
+ gap: 0.67em;
697
+ margin: 0 0 0.55em;
698
+ color: var(--pm-color-accent);
699
+ font-size: 0.67em;
700
+ font-weight: 600;
701
+ letter-spacing: 0.08em;
702
+ line-height: 1.4;
703
+ }
704
+
705
+ .pm-slide__chapter::after {
706
+ content: '';
707
+ flex: 1;
708
+ height: var(--pm-size-hairline);
709
+ background: var(--pm-color-line);
710
+ }
711
+
712
+ .pm-slide__body {
713
+ flex: 1;
650
714
  min-height: 0;
651
- max-width: min(92vw, 120rem);
652
- margin: 0 auto;
653
- padding: 5vh 4vw;
654
715
  overflow: hidden;
655
- font-size: clamp(1rem, min(2vw, 3.6vh), 1.75rem);
656
716
  }
657
717
 
658
- .pm-present__content {
718
+ .pm-slide__content {
659
719
  transform-origin: top left;
660
720
  }
661
721
 
662
- .pm-present .pm-present__slide :is(table, th, td) {
663
- font-size: 1em;
722
+ .pm-slide__content > .pm-block--markdown :is(p, ul, ol, blockquote) {
723
+ font-family: var(--pm-font-serif);
664
724
  }
665
725
 
666
- .pm-present .pm-present__slide :is(th, td) {
667
- padding: 0.3em 0.6em;
726
+ /* Over the reading styles of the document's headings (`.pm-document h2`). */
727
+ .pm-slide .pm-slide__title {
728
+ margin: 0 0 0.45em;
729
+ padding: 0;
730
+ border: 0;
731
+ font-family: var(--pm-font-serif);
732
+ font-size: 2.2em;
733
+ font-weight: 600;
734
+ line-height: 1.15;
735
+ letter-spacing: -0.005em;
668
736
  }
669
737
 
670
- .pm-present .pm-present__slide ul {
671
- padding-inline-start: 1.5em;
738
+ .pm-slide--cover {
739
+ justify-content: flex-end;
740
+ padding-bottom: 5.3em;
672
741
  }
673
742
 
674
- .pm-present .pm-present__slide ol {
675
- padding-inline-start: 2em;
743
+ .pm-slide--cover .pm-slide__title {
744
+ max-width: 85%;
745
+ font-size: 2.67em;
746
+ line-height: 1.12;
747
+ }
748
+
749
+ .pm-slide--cover .pm-slide__title::before {
750
+ content: '';
751
+ display: block;
752
+ width: 1em;
753
+ height: 0.07em;
754
+ margin-bottom: 0.45em;
755
+ border-radius: var(--pm-radius-chip);
756
+ background: var(--pm-color-accent);
757
+ }
758
+
759
+ .pm-slide--cover .pm-slide__content > .pm-block :is(p, ul, ol) {
760
+ max-width: 80%;
761
+ color: var(--pm-color-muted);
762
+ font-size: 1.1em;
763
+ }
764
+
765
+ .pm-slide--center .pm-slide__content {
766
+ display: flex;
767
+ flex-direction: column;
768
+ align-items: center;
769
+ justify-content: center;
770
+ min-height: 100%;
771
+ text-align: center;
772
+ }
773
+
774
+ .pm-slide--full {
775
+ padding: 0;
776
+ }
777
+
778
+ /* A full slide is all content (a scene, a picture); its title stays for assistive technology only. */
779
+ .pm-slide--full .pm-slide__title {
780
+ position: absolute;
781
+ width: var(--pm-size-hairline);
782
+ height: var(--pm-size-hairline);
783
+ margin: 0;
784
+ overflow: hidden;
785
+ clip: rect(0 0 0 0);
786
+ white-space: nowrap;
787
+ }
788
+
789
+ .pm-slide__footer {
790
+ position: absolute;
791
+ right: 3.1em;
792
+ bottom: 0.9em;
793
+ left: 3.1em;
794
+ display: flex;
795
+ align-items: center;
796
+ gap: 0.67em;
797
+ color: var(--pm-color-muted);
798
+ font-size: 0.61em;
799
+ line-height: 1.2;
800
+ }
801
+
802
+ .pm-slide__deck {
803
+ min-width: 0;
804
+ overflow: hidden;
805
+ text-overflow: ellipsis;
806
+ white-space: nowrap;
807
+ }
808
+
809
+ .pm-slide__steps {
810
+ display: flex;
811
+ flex: none;
812
+ gap: 0.45em;
813
+ width: min(calc(var(--pm-slide-steps, 1) * 2em - 0.45em), 40%);
814
+ margin-left: auto;
815
+ }
816
+
817
+ .pm-slide__steps > span {
818
+ flex: 1;
819
+ min-width: 0.2em;
820
+ height: 0.27em;
821
+ border-radius: 0.2em;
822
+ background: var(--pm-color-line-strong);
823
+ }
824
+
825
+ .pm-slide__steps > span[data-done] {
826
+ background: var(--pm-color-accent);
827
+ }
828
+
829
+ .pm-slide__page {
830
+ margin-left: auto;
831
+ font-family: var(--pm-font-mono);
832
+ font-variant-numeric: tabular-nums;
833
+ white-space: nowrap;
834
+ }
835
+
836
+ .pm-slide__steps + .pm-slide__page {
837
+ margin-left: 0;
838
+ }
839
+
840
+ /* A runnable code block's code, edited before it runs (CodeMirror). */
841
+ .pm-code-editor {
842
+ margin: 0.5em 0;
843
+ border: var(--pm-size-hairline) solid var(--pm-color-line-strong);
844
+ border-radius: var(--pm-radius-control);
845
+ background: var(--pm-color-code);
846
+ font-size: 0.875em;
847
+ }
848
+
849
+ .pm-code-editor .cm-editor {
850
+ border-radius: inherit;
851
+ }
852
+
853
+ .pm-code-editor .cm-editor.cm-focused {
854
+ outline: var(--pm-size-stroke) solid var(--pm-color-accent);
855
+ outline-offset: var(--pm-space-px);
856
+ }
857
+
858
+ .pm-code-editor .cm-scroller {
859
+ padding: 0.5em 0;
860
+ font-family: var(--pm-font-mono);
861
+ line-height: 1.6;
862
+ }
863
+
864
+ .pm-code-editor .cm-content {
865
+ caret-color: var(--pm-color-ink);
866
+ color: var(--pm-color-ink);
867
+ }
868
+
869
+ .pm-code-editor .cm-cursor {
870
+ border-left-color: var(--pm-color-ink);
871
+ }
872
+
873
+ /* Plugins' layers on a slide (drawings): over its content, on the canvas's coordinates; a layer takes the pointer itself. */
874
+ .pm-slide__layers {
875
+ position: absolute;
876
+ inset: 0;
877
+ pointer-events: none;
878
+ }
879
+
880
+ /* Every slide one after the other at the canvas's size, for printing. */
881
+
882
+ .pm-slides-print__page {
883
+ position: relative;
884
+ overflow: hidden;
885
+ break-after: page;
886
+ }
887
+
888
+ @media print {
889
+ @page {
890
+ margin: 0;
891
+ }
892
+
893
+ html,
894
+ body {
895
+ margin: 0;
896
+ }
676
897
  }
677
898
 
678
899
  .pm-overview {
@@ -685,7 +906,8 @@ html.pm-presenting {
685
906
  font-size: 1rem;
686
907
  }
687
908
 
688
- .pm-overview__grid {
909
+ /* The overview is chrome inside a document: its own list rules outrank the document's list styling. */
910
+ .pm-overview .pm-overview__grid {
689
911
  display: grid;
690
912
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
691
913
  gap: 0.75rem;
@@ -701,7 +923,7 @@ html.pm-presenting {
701
923
  width: 100%;
702
924
  min-height: 4.5rem;
703
925
  padding: 0.75rem;
704
- border: 1px solid var(--pm-c-border);
926
+ border: var(--pm-size-hairline) solid var(--pm-c-border);
705
927
  border-radius: 0.375rem;
706
928
  background: var(--pm-c-bg-soft);
707
929
  color: var(--pm-c-text);
@@ -711,12 +933,12 @@ html.pm-presenting {
711
933
 
712
934
  .pm-overview__item[aria-current='true'] {
713
935
  border-color: var(--pm-c-brand);
714
- box-shadow: inset 0 0 0 1px var(--pm-c-brand);
936
+ box-shadow: inset 0 0 0 var(--pm-size-hairline) var(--pm-c-brand);
715
937
  }
716
938
 
717
939
  .pm-overview__item:focus-visible {
718
- outline: 2px solid var(--pm-c-brand);
719
- outline-offset: 2px;
940
+ outline: var(--pm-size-stroke) solid var(--pm-c-brand);
941
+ outline-offset: var(--pm-size-stroke);
720
942
  }
721
943
 
722
944
  .pm-overview__index {
@@ -739,7 +961,7 @@ html.pm-presenting {
739
961
  gap: 0.5rem;
740
962
  align-items: center;
741
963
  padding: 0.5rem 1rem;
742
- border-top: 1px solid var(--pm-c-border);
964
+ border-top: var(--pm-size-hairline) solid var(--pm-c-border);
743
965
  font-size: 0.875rem;
744
966
  color: var(--pm-c-text-2);
745
967
  }
@@ -750,7 +972,7 @@ html.pm-presenting {
750
972
 
751
973
  .pm-present__button {
752
974
  padding: 0.25rem 0.75rem;
753
- border: 1px solid var(--pm-c-border);
975
+ border: var(--pm-size-hairline) solid var(--pm-c-border);
754
976
  border-radius: 0.25rem;
755
977
  background: var(--pm-c-bg-soft);
756
978
  color: var(--pm-c-text);
@@ -759,7 +981,7 @@ html.pm-presenting {
759
981
 
760
982
  .pm-presenter__bar {
761
983
  border-top: none;
762
- border-bottom: 1px solid var(--pm-c-border);
984
+ border-bottom: var(--pm-size-hairline) solid var(--pm-c-border);
763
985
  }
764
986
 
765
987
  .pm-presenter__title {
@@ -768,7 +990,7 @@ html.pm-presenting {
768
990
 
769
991
  .pm-presenter__timer {
770
992
  margin-left: auto;
771
- font-family: var(--vp-font-family-mono, monospace);
993
+ font-family: var(--pm-font-mono);
772
994
  font-size: 1.25rem;
773
995
  color: var(--pm-c-text);
774
996
  }
@@ -789,9 +1011,12 @@ html.pm-presenting {
789
1011
  }
790
1012
 
791
1013
  .pm-presenter__slide {
792
- padding: 1rem;
793
- border: 1px solid var(--pm-c-border);
794
- border-radius: 0.5rem;
1014
+ min-height: 0;
1015
+ }
1016
+
1017
+ .pm-presenter__upcoming {
1018
+ aspect-ratio: 16 / 9;
1019
+ margin-bottom: 0.5rem;
795
1020
  }
796
1021
 
797
1022
  .pm-presenter .pm-presenter__label {
@@ -802,7 +1027,7 @@ html.pm-presenting {
802
1027
 
803
1028
  .pm-presenter__note {
804
1029
  padding: 0 0.5rem;
805
- border-left: 3px solid transparent;
1030
+ border-left: var(--pm-size-rule) solid transparent;
806
1031
  opacity: 0.5;
807
1032
  }
808
1033
 
@@ -824,10 +1049,10 @@ html.pm-presenting {
824
1049
  .pm-role-mark {
825
1050
  margin: 0 0.15em;
826
1051
  padding: 0 0.2em;
827
- border-radius: 3px;
1052
+ border-radius: var(--pm-radius-chip);
828
1053
  font-size: 0.85em;
829
- color: var(--vp-c-text-2, #666);
830
- background: var(--vp-c-default-soft, rgba(128, 128, 128, 0.15));
1054
+ color: var(--pm-color-muted);
1055
+ background: var(--pm-color-sunk);
831
1056
  }
832
1057
 
833
1058
  .pm-step-range.pm-hidden { display: none !important; }
@@ -0,0 +1,7 @@
1
+ import { currentLocale } from '@lincyaw/host'
2
+ import { VIEWER_MESSAGES } from '../domain/index.ts'
3
+ import type { Messages } from '../domain/index.ts'
4
+
5
+ export function viewerMessages(): Messages {
6
+ return VIEWER_MESSAGES[currentLocale()]
7
+ }
@@ -2,7 +2,7 @@ import { errorMessage } from '@lincyaw/kernel'
2
2
  import { BlockView } from './block.ts'
3
3
  import { registerAction, registerComponent, registerLayer, registerNodeRenderer, registerView } from './registry.ts'
4
4
  import { SectionView } from './section.ts'
5
- import { useViewer } from './viewer.ts'
5
+ import { useViewer } from './viewer-state.ts'
6
6
 
7
7
  export interface ViewerPluginContext {
8
8
  registerView: typeof registerView
@@ -19,7 +19,8 @@ export type ViewerPlugin = (context: ViewerPluginContext) => void
19
19
 
20
20
  const context: ViewerPluginContext = { registerView, registerNodeRenderer, registerComponent, registerAction, registerLayer, useViewer, SectionView, BlockView }
21
21
 
22
- export function installViewerPlugin(plugin: unknown, name = 'viewer plugin'): string | undefined {
22
+ /** Installs a viewer plugin; returns why it could not be installed, or undefined when it was. */
23
+ export function tryInstallViewerPlugin(plugin: unknown, name = 'viewer plugin'): string | undefined {
23
24
  if (typeof plugin !== 'function') {
24
25
  console.error(`[presmium] ${name}: the default export is not a function`)
25
26
  return 'the default export is not a function'