rikiki-deck 0.7.1 → 0.7.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 (103) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/browser.mjs +24 -1
  3. package/bin/lib/check-api.d.ts +28 -0
  4. package/bin/lib/check-api.mjs +6 -0
  5. package/bin/lib/check-plugins.mjs +228 -0
  6. package/bin/lib/check.mjs +369 -14
  7. package/bin/lib/component-deps.mjs +69 -0
  8. package/bin/lib/export-pdf.mjs +28 -5
  9. package/bin/lib/inline.mjs +70 -35
  10. package/bin/lib/narrative.mjs +77 -0
  11. package/bin/lib/prune-icons.mjs +24 -1
  12. package/bin/rikiki.mjs +45 -7
  13. package/dist/{plugins/click-stages.d.ts → click-stages.d.ts} +1 -1
  14. package/dist/{layouts/deck-cover.d.ts → deck-cover.d.ts} +2 -0
  15. package/dist/deck-cover.js +9 -6
  16. package/dist/{atoms/deck-kicker.d.ts → deck-kicker.d.ts} +5 -0
  17. package/dist/deck-kicker.js +1 -1
  18. package/dist/deck-mermaid.js +4 -4
  19. package/dist/deck-overview.js +41 -40
  20. package/dist/deck-presenter.js +89 -46
  21. package/dist/{runtime/deck-root.d.ts → deck-root.d.ts} +14 -3
  22. package/dist/deck-root.js +5 -5
  23. package/dist/{extras/deck-timeline.d.ts → deck-timeline.d.ts} +6 -0
  24. package/dist/deck-timeline.js +4 -4
  25. package/dist/deck-versus.js +2 -2
  26. package/dist/index.d.ts +37 -37
  27. package/dist/index.js +55 -52
  28. package/dist/standalone.js +229 -182
  29. package/dist/vendor/THIRD-PARTY-NOTICES.txt +3 -3
  30. package/dist/vendor/inventory.json +7 -7
  31. package/dist/vendor/mermaid.min.js +95 -95
  32. package/docs/llms/rikiki-reference.md +31 -4
  33. package/llms.txt +1 -1
  34. package/package.json +13 -6
  35. package/dist/contrast.js +0 -1
  36. package/dist/shared/contrast.d.ts +0 -52
  37. /package/dist/{shared/annotation-marks.d.ts → annotation-marks.d.ts} +0 -0
  38. /package/dist/{shared/bar-segments.d.ts → bar-segments.d.ts} +0 -0
  39. /package/dist/{infrastructure/browser-location.d.ts → browser-location.d.ts} +0 -0
  40. /package/dist/{shared/cards-syntax.d.ts → cards-syntax.d.ts} +0 -0
  41. /package/dist/{runtime/color.d.ts → color.d.ts} +0 -0
  42. /package/dist/{extras/deck-agenda.d.ts → deck-agenda.d.ts} +0 -0
  43. /package/dist/{extras/deck-annotate.d.ts → deck-annotate.d.ts} +0 -0
  44. /package/dist/{atoms/deck-badge.d.ts → deck-badge.d.ts} +0 -0
  45. /package/dist/{extras/deck-bar.d.ts → deck-bar.d.ts} +0 -0
  46. /package/dist/{layouts/deck-bento.d.ts → deck-bento.d.ts} +0 -0
  47. /package/dist/{molecules/deck-callout.d.ts → deck-callout.d.ts} +0 -0
  48. /package/dist/{molecules/deck-card.d.ts → deck-card.d.ts} +0 -0
  49. /package/dist/{molecules/deck-cell.d.ts → deck-cell.d.ts} +0 -0
  50. /package/dist/{extras/deck-checklist.d.ts → deck-checklist.d.ts} +0 -0
  51. /package/dist/{atoms/deck-code-highlighter.d.ts → deck-code-highlighter.d.ts} +0 -0
  52. /package/dist/{atoms/deck-code.d.ts → deck-code.d.ts} +0 -0
  53. /package/dist/{molecules/deck-csv.d.ts → deck-csv.d.ts} +0 -0
  54. /package/dist/{layouts/deck-feature-cards.d.ts → deck-feature-cards.d.ts} +0 -0
  55. /package/dist/{layouts/deck-feature.d.ts → deck-feature.d.ts} +0 -0
  56. /package/dist/{extras/deck-figure.d.ts → deck-figure.d.ts} +0 -0
  57. /package/dist/{molecules/deck-fit.d.ts → deck-fit.d.ts} +0 -0
  58. /package/dist/{extras/deck-flow.d.ts → deck-flow.d.ts} +0 -0
  59. /package/dist/{extras/deck-graph.d.ts → deck-graph.d.ts} +0 -0
  60. /package/dist/{molecules/deck-grid.d.ts → deck-grid.d.ts} +0 -0
  61. /package/dist/{runtime/deck-help.d.ts → deck-help.d.ts} +0 -0
  62. /package/dist/{extras/deck-icon.d.ts → deck-icon.d.ts} +0 -0
  63. /package/dist/{extras/deck-kpi-grid.d.ts → deck-kpi-grid.d.ts} +0 -0
  64. /package/dist/{domain/deck-link.d.ts → deck-link.d.ts} +0 -0
  65. /package/dist/{molecules/deck-md.d.ts → deck-md.d.ts} +0 -0
  66. /package/dist/{molecules/deck-mermaid.d.ts → deck-mermaid.d.ts} +0 -0
  67. /package/dist/{molecules/deck-metric.d.ts → deck-metric.d.ts} +0 -0
  68. /package/dist/{runtime/deck-notes.d.ts → deck-notes.d.ts} +0 -0
  69. /package/dist/{domain/deck-outline.d.ts → deck-outline.d.ts} +0 -0
  70. /package/dist/{runtime/deck-overview.d.ts → deck-overview.d.ts} +0 -0
  71. /package/dist/{extras/deck-persona.d.ts → deck-persona.d.ts} +0 -0
  72. /package/dist/{layouts/deck-photo.d.ts → deck-photo.d.ts} +0 -0
  73. /package/dist/{molecules/deck-point.d.ts → deck-point.d.ts} +0 -0
  74. /package/dist/{runtime/deck-presenter.d.ts → deck-presenter.d.ts} +0 -0
  75. /package/dist/{extras/deck-pull.d.ts → deck-pull.d.ts} +0 -0
  76. /package/dist/{atoms/deck-punch.d.ts → deck-punch.d.ts} +0 -0
  77. /package/dist/{extras/deck-quote.d.ts → deck-quote.d.ts} +0 -0
  78. /package/dist/{layouts/deck-section.d.ts → deck-section.d.ts} +0 -0
  79. /package/dist/{molecules/deck-shortcut.d.ts → deck-shortcut.d.ts} +0 -0
  80. /package/dist/{atoms/deck-source.d.ts → deck-source.d.ts} +0 -0
  81. /package/dist/{layouts/deck-split.d.ts → deck-split.d.ts} +0 -0
  82. /package/dist/{molecules/deck-stack.d.ts → deck-stack.d.ts} +0 -0
  83. /package/dist/{molecules/deck-stat.d.ts → deck-stat.d.ts} +0 -0
  84. /package/dist/{molecules/deck-step-list.d.ts → deck-step-list.d.ts} +0 -0
  85. /package/dist/{extras/deck-table.d.ts → deck-table.d.ts} +0 -0
  86. /package/dist/{layouts/deck-takeaway.d.ts → deck-takeaway.d.ts} +0 -0
  87. /package/dist/{molecules/deck-tier-list.d.ts → deck-tier-list.d.ts} +0 -0
  88. /package/dist/{runtime/deck-transition.d.ts → deck-transition.d.ts} +0 -0
  89. /package/dist/{extras/deck-versus.d.ts → deck-versus.d.ts} +0 -0
  90. /package/dist/{application/deep-link.d.ts → deep-link.d.ts} +0 -0
  91. /package/dist/{shared/escape-html.d.ts → escape-html.d.ts} +0 -0
  92. /package/dist/{shared/fit-controller.d.ts → fit-controller.d.ts} +0 -0
  93. /package/dist/{shared/graph-layout.d.ts → graph-layout.d.ts} +0 -0
  94. /package/dist/{shared/grid-tracks.d.ts → grid-tracks.d.ts} +0 -0
  95. /package/dist/{shared/icon-set.d.ts → icon-set.d.ts} +0 -0
  96. /package/dist/{application/keymap.d.ts → keymap.d.ts} +0 -0
  97. /package/dist/{application/mouse-nav.d.ts → mouse-nav.d.ts} +0 -0
  98. /package/dist/{domain/navigation.d.ts → navigation.d.ts} +0 -0
  99. /package/dist/{shared/parse-csv.d.ts → parse-csv.d.ts} +0 -0
  100. /package/dist/{plugins/shiki.d.ts → shiki.d.ts} +0 -0
  101. /package/dist/{extras/signature.d.ts → signature.d.ts} +0 -0
  102. /package/dist/{shared/slide-fill.d.ts → slide-fill.d.ts} +0 -0
  103. /package/dist/{domain/viewport.d.ts → viewport.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
- var I="data-deck-overview",O="data-overview-tokens",P=`
1
+ var F="data-deck-overview",K=new WeakMap,R=new WeakMap;function J(t){let r=t.outerHTML,o=r.indexOf(">");return r.slice(0,o).replace(/\sactive(?:="[^"]*")?/,"")+r.slice(o)}var Q=`
2
2
  :host([overview]) ::slotted(*) { display: none !important; }
3
- :host([overview]) #overview-grid {
3
+ :host(:is([overview], [data-overview-warming])) #overview-grid {
4
4
  position: fixed; inset: 0;
5
5
  background: var(--rik-surface-page);
6
6
  overflow: hidden;
@@ -10,7 +10,7 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
10
10
  }
11
11
 
12
12
  /* \u2500\u2500 Top bar \xB7 search, slide count, close hint \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
13
- :host([overview]) .ov-bar {
13
+ :host(:is([overview], [data-overview-warming])) .ov-bar {
14
14
  display: flex; align-items: center; gap: 16px;
15
15
  padding: 14px 28px;
16
16
  background: var(--rik-surface-raised);
@@ -19,7 +19,7 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
19
19
  letter-spacing: 0.10em;
20
20
  color: var(--rik-text-default--faint);
21
21
  }
22
- :host([overview]) .ov-bar .ov-search {
22
+ :host(:is([overview], [data-overview-warming])) .ov-bar .ov-search {
23
23
  flex: 1;
24
24
  appearance: none;
25
25
  background: var(--rik-surface-raised--strong);
@@ -31,28 +31,28 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
31
31
  letter-spacing: 0;
32
32
  max-width: 480px;
33
33
  }
34
- :host([overview]) .ov-bar .ov-search:focus {
34
+ :host(:is([overview], [data-overview-warming])) .ov-bar .ov-search:focus {
35
35
  outline: none;
36
36
  border-color: var(--rik-accent);
37
37
  box-shadow: 0 0 0 3px var(--rik-accent--soft);
38
38
  }
39
- :host([overview]) .ov-bar .ov-count { color: var(--rik-accent); }
40
- :host([overview]) .ov-bar .ov-hint { letter-spacing: 0.16em; text-transform: uppercase; }
39
+ :host(:is([overview], [data-overview-warming])) .ov-bar .ov-count { color: var(--rik-accent); }
40
+ :host(:is([overview], [data-overview-warming])) .ov-bar .ov-hint { letter-spacing: 0.16em; text-transform: uppercase; }
41
41
 
42
42
  /* \u2500\u2500 Sidebar layout (many slides) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
43
- :host([overview]) .ov-body {
43
+ :host(:is([overview], [data-overview-warming])) .ov-body {
44
44
  display: grid;
45
45
  grid-template-columns: 240px 1fr;
46
46
  min-height: 0;
47
47
  }
48
- :host([overview]) .ov-body.compact { grid-template-columns: 1fr; }
49
- :host([overview]) .ov-aside {
48
+ :host(:is([overview], [data-overview-warming])) .ov-body.compact { grid-template-columns: 1fr; }
49
+ :host(:is([overview], [data-overview-warming])) .ov-aside {
50
50
  border-right: 1px solid var(--rik-border-default);
51
51
  background: var(--rik-surface-raised);
52
52
  overflow-y: auto;
53
53
  padding: 16px 0;
54
54
  }
55
- :host([overview]) .ov-aside-item {
55
+ :host(:is([overview], [data-overview-warming])) .ov-aside-item {
56
56
  display: grid;
57
57
  grid-template-columns: 36px 1fr;
58
58
  gap: 10px;
@@ -63,84 +63,84 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
63
63
  color: var(--rik-text-default--muted);
64
64
  transition: background 0.12s, color 0.12s, border-color 0.12s;
65
65
  }
66
- :host([overview]) .ov-aside-item:hover {
66
+ :host(:is([overview], [data-overview-warming])) .ov-aside-item:hover {
67
67
  background: var(--rik-surface-tint);
68
68
  color: var(--rik-text-default);
69
69
  }
70
- :host([overview]) .ov-aside-item[data-active] {
70
+ :host(:is([overview], [data-overview-warming])) .ov-aside-item[data-active] {
71
71
  background: var(--rik-accent--faint);
72
72
  border-left-color: var(--rik-accent);
73
73
  color: var(--rik-text-default);
74
74
  }
75
- :host([overview]) .ov-aside-num {
75
+ :host(:is([overview], [data-overview-warming])) .ov-aside-num {
76
76
  font: 800 0.85rem/1 var(--rik-font-mono);
77
77
  color: var(--rik-accent);
78
78
  }
79
- :host([overview]) .ov-aside-text {
79
+ :host(:is([overview], [data-overview-warming])) .ov-aside-text {
80
80
  font: 700 0.92rem/1.3 var(--rik-font-display, var(--rik-font-sans));
81
81
  letter-spacing: -0.005em;
82
82
  }
83
- :host([overview]) .ov-aside-count {
83
+ :host(:is([overview], [data-overview-warming])) .ov-aside-count {
84
84
  font: 600 0.70rem/1 var(--rik-font-mono);
85
85
  color: var(--rik-text-default--faint);
86
86
  margin-top: 4px;
87
87
  }
88
88
 
89
89
  /* \u2500\u2500 Main scroll area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
90
- :host([overview]) .ov-main {
90
+ :host(:is([overview], [data-overview-warming])) .ov-main {
91
91
  overflow-y: auto;
92
92
  padding: 24px 32px 48px;
93
93
  display: flex; flex-direction: column;
94
94
  gap: 32px;
95
95
  min-width: 0;
96
96
  }
97
- :host([overview]) .ov-chapter {
97
+ :host(:is([overview], [data-overview-warming])) .ov-chapter {
98
98
  display: flex; flex-direction: column;
99
99
  gap: 12px;
100
100
  scroll-margin-top: 24px;
101
101
  }
102
- :host([overview]) .ov-chapter-head {
102
+ :host(:is([overview], [data-overview-warming])) .ov-chapter-head {
103
103
  display: flex; align-items: baseline; gap: 12px;
104
104
  padding-bottom: 6px;
105
105
  border-bottom: 2px solid var(--rik-accent);
106
106
  }
107
- :host([overview]) .ov-chapter-num {
107
+ :host(:is([overview], [data-overview-warming])) .ov-chapter-num {
108
108
  font: 800 0.85rem/1 var(--rik-font-mono);
109
109
  color: var(--rik-accent);
110
110
  letter-spacing: 0.12em;
111
111
  }
112
- :host([overview]) .ov-chapter-title {
112
+ :host(:is([overview], [data-overview-warming])) .ov-chapter-title {
113
113
  font: 800 1.2rem/1.2 var(--rik-font-display, var(--rik-font-sans));
114
114
  color: var(--rik-text-default);
115
115
  letter-spacing: -0.012em;
116
116
  flex: 1;
117
117
  min-width: 0;
118
118
  }
119
- :host([overview]) .ov-chapter-count {
119
+ :host(:is([overview], [data-overview-warming])) .ov-chapter-count {
120
120
  font: 700 0.72rem/1 var(--rik-font-mono);
121
121
  color: var(--rik-text-default--faint);
122
122
  letter-spacing: 0.1em;
123
123
  text-transform: uppercase;
124
124
  }
125
- :host([overview]) .ov-row {
125
+ :host(:is([overview], [data-overview-warming])) .ov-row {
126
126
  display: grid;
127
127
  grid-template-columns: repeat(auto-fill, minmax(var(--ov-cell-min, 180px), 1fr));
128
128
  gap: 12px;
129
129
  }
130
130
 
131
131
  /* \u2500\u2500 Path layout (\u2264 60 slides) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
132
- :host([overview]) .ov-path .ov-row {
132
+ :host(:is([overview], [data-overview-warming])) .ov-path .ov-row {
133
133
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
134
134
  }
135
- :host([overview]) .ov-path .ov-connector {
135
+ :host(:is([overview], [data-overview-warming])) .ov-path .ov-connector {
136
136
  flex: 0 0 auto;
137
137
  width: 16px; height: 2px;
138
138
  background: var(--rik-border-default);
139
139
  }
140
- :host([overview]) .ov-path .ov-cell { flex: 0 0 auto; width: clamp(160px, 14vw, 260px); }
140
+ :host(:is([overview], [data-overview-warming])) .ov-path .ov-cell { flex: 0 0 auto; width: clamp(160px, 14vw, 260px); }
141
141
 
142
142
  /* \u2500\u2500 Thumbnail cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
143
- :host([overview]) .ov-cell {
143
+ :host(:is([overview], [data-overview-warming])) .ov-cell {
144
144
  position: relative;
145
145
  aspect-ratio: 16 / 9;
146
146
  background:
@@ -160,24 +160,24 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
160
160
  }
161
161
  /* The keyboard user must see where they are \xB7 without this the grid moves
162
162
  focus invisibly. */
163
- :host([overview]) .ov-cell:focus-visible {
163
+ :host(:is([overview], [data-overview-warming])) .ov-cell:focus-visible {
164
164
  outline: var(--rik-focus-ring--width, 2px) solid var(--rik-focus-ring, currentColor);
165
165
  outline-offset: var(--rik-focus-ring--offset, 2px);
166
166
  z-index: 2;
167
167
  }
168
- :host([overview]) .ov-cell:hover {
168
+ :host(:is([overview], [data-overview-warming])) .ov-cell:hover {
169
169
  transform: translateY(-2px) scale(1.015);
170
170
  border-color: var(--rik-accent--soft);
171
171
  box-shadow: var(--rik-elevation-3);
172
172
  z-index: 1;
173
173
  }
174
- :host([overview]) .ov-cell[data-current] {
174
+ :host(:is([overview], [data-overview-warming])) .ov-cell[data-current] {
175
175
  border-color: var(--rik-accent);
176
176
  box-shadow: 0 0 0 3px var(--rik-accent--soft), var(--rik-elevation-2);
177
177
  }
178
- :host([overview]) .ov-cell[data-filtered-out] { opacity: 0.10; pointer-events: none; transform: scale(0.96); }
179
- :host([overview]) .ov-cell:not([data-loaded]) .ov-thumb { display: none; }
180
- :host([overview]) .ov-cell:not([data-loaded])::before {
178
+ :host(:is([overview], [data-overview-warming])) .ov-cell[data-filtered-out] { opacity: 0.10; pointer-events: none; transform: scale(0.96); }
179
+ :host(:is([overview], [data-overview-warming])) .ov-cell:not([data-loaded]) .ov-thumb { display: none; }
180
+ :host(:is([overview], [data-overview-warming])) .ov-cell:not([data-loaded])::before {
181
181
  content: '';
182
182
  position: absolute; inset: 0;
183
183
  background:
@@ -197,7 +197,7 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
197
197
  /* The thumb mirrors the letterboxed stage, so make it a size container too \xB7
198
198
  the cloned slide's cqw/cqh then resolve exactly as they do live instead of
199
199
  falling back to the (larger) window. */
200
- :host([overview]) .ov-thumb {
200
+ :host(:is([overview], [data-overview-warming])) .ov-thumb {
201
201
  position: absolute; top: 0; left: 0;
202
202
  width: var(--ov-thumb-w, 1920px); height: var(--ov-thumb-h, 1080px);
203
203
  transform: scale(var(--overview-scale, 0.2));
@@ -205,8 +205,8 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
205
205
  pointer-events: none;
206
206
  container-type: size;
207
207
  }
208
- :host([overview]) .ov-thumb > * { display: flex !important; }
209
- :host([overview]) .ov-mermaid-snap {
208
+ :host(:is([overview], [data-overview-warming])) .ov-thumb > * { display: flex !important; }
209
+ :host(:is([overview], [data-overview-warming])) .ov-mermaid-snap {
210
210
  display: flex; align-items: center; justify-content: center;
211
211
  background: var(--rik-code__bg);
212
212
  border: 1px solid var(--rik-code__border);
@@ -214,11 +214,11 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
214
214
  padding: var(--rik-space-4);
215
215
  overflow: hidden; min-width: 0;
216
216
  }
217
- :host([overview]) .ov-mermaid-snap svg {
217
+ :host(:is([overview], [data-overview-warming])) .ov-mermaid-snap svg {
218
218
  width: 100% !important; height: auto !important;
219
219
  max-width: 100% !important; max-height: 60cqh;
220
220
  }
221
- :host([overview]) .ov-cell-label {
221
+ :host(:is([overview], [data-overview-warming])) .ov-cell-label {
222
222
  position: absolute; bottom: 6px; right: 8px;
223
223
  font: 700 0.70rem/1 var(--rik-font-mono);
224
224
  color: var(--rik-text-default);
@@ -227,5 +227,6 @@ var I="data-deck-overview",O="data-overview-tokens",P=`
227
227
  z-index: 2;
228
228
  pointer-events: none;
229
229
  }
230
- :host(:not([overview])) #overview-grid { display: none; }
231
- `;function W(r){if(r.querySelector(`style[${I}]`))return;let o=document.createElement("style");o.setAttribute(I,"1"),o.textContent=P,r.appendChild(o)}function _(r,o){if(r.querySelector(`link[${O}]`))return;let t=document.createElement("link");t.rel="stylesheet",t.setAttribute(O,"1"),t.href=new URL("../tokens.css",o).href,r.appendChild(t)}function R(r){let t=r.slides[0]?.querySelector("h1");return t?Array.from(t.childNodes).map(e=>e.nodeName==="BR"?" ":e.textContent??"").join("").replace(/\s+/g," ").trim()||`Slide ${r.startIdx+1}`:`Slide ${r.startIdx+1}`}function z(r){return(r.textContent||"").replace(/\s+/g," ").trim().slice(0,400).toLowerCase()}var B=["fill","stroke","clip-path","mask","filter","marker-start","marker-mid","marker-end","style"];function D(r,o){let t=new Map;if(r.querySelectorAll("[id]").forEach(a=>{t.set(a.id,a.id+o),a.id=a.id+o}),t.size===0)return;let e=a=>a.replace(/url\(['"]?#([^'")]+)['"]?\)/g,(s,d)=>t.has(d)?`url(#${t.get(d)})`:s);r.querySelectorAll("*").forEach(a=>{for(let s of B){let d=a.getAttribute(s);d?.includes("url(")&&a.setAttribute(s,e(d))}for(let s of["href","xlink:href"]){let d=a.getAttribute(s);d?.startsWith("#")&&t.has(d.slice(1))&&a.setAttribute(s,`#${t.get(d.slice(1))}`)}});let u=r.querySelectorAll("style");if(u.length){let a=s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");u.forEach(s=>{let d=s.textContent??"";t.forEach((w,S)=>{d=d.replace(new RegExp(`#${a(S)}(?![\\w-])`,"g"),`#${w}`)}),s.textContent=d})}}function V(r,o){let t=r.querySelectorAll("svg");o.querySelectorAll("svg").forEach((e,u)=>{let a=t[u]?.getBoundingClientRect();if(a&&a.width>0)e.setAttribute("width",String(Math.round(a.width))),e.setAttribute("height",String(Math.round(a.height))),e.style.maxWidth="100%";else if(e.hasAttribute("viewBox")&&!e.hasAttribute("width")){let s=(e.getAttribute("viewBox")??"").split(/[\s,]+/).map(Number);s.length===4&&s[2]>0&&(e.setAttribute("width",String(s[2])),e.setAttribute("height",String(s[3])),e.style.maxWidth="100%",e.style.height="auto")}})}function G(r,o){let t=r.querySelectorAll("deck-mermaid");o.querySelectorAll("deck-mermaid").forEach((e,u)=>{let a=t[u],s=document.createElement("div");s.className="ov-mermaid-snap",s.innerHTML=a?.renderedSvg??"";let d=a?.getBoundingClientRect();d&&d.width>0&&(s.style.width=`${d.width}px`,s.style.height=`${d.height}px`),e.replaceWith(s)})}function U(r){r.querySelectorAll("[data-click], [data-click-auto], [data-click-children], [data-click-stagger] > *").forEach(o=>{o.style.opacity="",o.style.transform="",o.style.filter="",o.style.pointerEvents="",o.querySelectorAll("path, line, polyline, polygon, circle, ellipse, rect").forEach(t=>{t.style.strokeDashoffset=""})})}function F(r,o){let t=r.cloneNode(!0);return t.setAttribute("active",""),U(t),V(r,t),G(r,t),D(t,`-ov${o}`),t}async function K(r,o){let t=Array.from(o.querySelectorAll("deck-mermaid")).map(u=>u.whenRendered).filter(u=>!!u);t.length&&await Promise.all(t).catch(()=>{});let e=document.createElement("div");e.className="ov-thumb",e.appendChild(F(o,Number(r.dataset.idx))),r.insertBefore(e,r.firstChild),r.dataset.loaded="1",delete r.dataset.building}function Y(r,o){let t=r.shadowRoot;if(!t)return()=>{};W(t),_(t,import.meta.url);let e=t.querySelector("#overview-grid");e||(e=document.createElement("div"),e.id="overview-grid",t.appendChild(e)),e.innerHTML="";let u=o.slides.length,a=u>60,s=u>300?140:u>150?160:u>60?180:220;e.style.setProperty("--ov-cell-min",`${s}px`);let d=t.querySelector("#stage"),w=d?.clientWidth||window.innerWidth,S=d?.clientHeight||window.innerHeight;e.style.setProperty("--ov-thumb-w",`${w}px`),e.style.setProperty("--ov-thumb-h",`${S}px`),requestAnimationFrame(()=>{let i=e.querySelector(".ov-cell")?.clientWidth??s;e.style.setProperty("--overview-scale",String(i/w))});let x=document.createElement("div");x.className="ov-bar";let f=document.createElement("input");f.className="ov-search",f.type="search",f.placeholder=`Search ${u} slides \xB7 type to filter`,f.spellcheck=!1,x.appendChild(f);let C=document.createElement("span");C.className="ov-count",C.textContent=`${u} slides \xB7 ${o.chapters.length} chapters`,x.appendChild(C);let L=document.createElement("span");L.className="ov-hint",L.textContent="O \xB7 Esc \xB7 close",x.appendChild(L),e.appendChild(x);let k=document.createElement("div");k.className=`ov-body${a?"":" compact"}`,e.appendChild(k);let b=a?document.createElement("aside"):null;b&&(b.className="ov-aside",k.appendChild(b));let y=document.createElement("div");y.className=`ov-main${a?"":" ov-path"}`,k.appendChild(y);let T=[],A=[],H=new WeakMap,E=new IntersectionObserver(i=>{for(let v of i){if(!v.isIntersecting)continue;let n=v.target;if(n.dataset.loaded||n.dataset.building)continue;let m=H.get(n);m&&(n.dataset.building="1",E.unobserve(n),K(n,m).catch(l=>{let h=Number(n.dataset.tries??"0")+1;n.dataset.tries=String(h),console.warn("[rikiki/overview] thumbnail build failed",l),delete n.dataset.building,h<3&&E.observe(n)}))}},{root:null,rootMargin:"300px 0px",threshold:0});o.chapters.forEach((i,v)=>{let n=document.createElement("section");if(n.className="ov-chapter",n.id=`ov-chapter-${v}`,a){let l=document.createElement("header");l.className="ov-chapter-head";let h=document.createElement("span");h.className="ov-chapter-num",h.textContent=String(v+1).padStart(2,"0"),l.appendChild(h);let p=document.createElement("span");p.className="ov-chapter-title",p.textContent=R(i),l.appendChild(p);let c=document.createElement("span");c.className="ov-chapter-count",c.textContent=`${i.slides.length} slide${i.slides.length>1?"s":""}`,l.appendChild(c),n.appendChild(l)}let m=document.createElement("div");if(m.className="ov-row",i.slides.forEach((l,h)=>{if(!a&&h>0){let q=document.createElement("div");q.className="ov-connector",m.appendChild(q)}let p=i.startIdx+h,c=document.createElement("button");c.type="button",c.className="ov-cell",c.dataset.idx=String(p),c.dataset.search=z(l),p===o.currentIdx&&(c.dataset.current="1"),H.set(c,l),E.observe(c);let g=document.createElement("span");g.className="ov-cell-label",g.textContent=String(p+1),c.appendChild(g);let $=z(l).trim().slice(0,80);c.setAttribute("aria-label",`Slide ${p+1} of ${u}${$?` \xB7 ${$}`:""}`),p===o.currentIdx&&c.setAttribute("aria-current","true"),c.addEventListener("click",()=>o.onPick(p)),m.appendChild(c)}),n.appendChild(m),y.appendChild(n),T.push(n),b){let l=document.createElement("button");l.type="button",l.className="ov-aside-item",o.currentIdx>=i.startIdx&&o.currentIdx<i.startIdx+i.slides.length&&(l.dataset.active="1");let p=document.createElement("span");p.className="ov-aside-num",p.textContent=String(v+1).padStart(2,"0"),l.appendChild(p);let c=document.createElement("span");c.className="ov-aside-text",c.textContent=R(i);let g=document.createElement("div");g.className="ov-aside-count",g.textContent=`${i.slides.length} slide${i.slides.length>1?"s":""}`,c.appendChild(g),l.appendChild(c),l.addEventListener("click",()=>{n.scrollIntoView({behavior:"smooth",block:"start"})}),b.appendChild(l),A.push(l)}});let M=null;b&&(M=new IntersectionObserver(i=>{let v=i.filter(n=>n.isIntersecting).sort((n,m)=>n.boundingClientRect.top-m.boundingClientRect.top);if(v.length>0){let n=T.indexOf(v[0].target);n>=0&&A.forEach((m,l)=>{l===n?m.dataset.active="1":delete m.dataset.active})}},{root:y,rootMargin:"0px 0px -70% 0px",threshold:0}),T.forEach(i=>{M.observe(i)}));let N=e.querySelectorAll(".ov-cell");return f.addEventListener("input",()=>{let i=f.value.trim().toLowerCase();if(!i){N.forEach(v=>{delete v.dataset.filteredOut});return}N.forEach(v=>{(v.dataset.search||"").includes(i)?delete v.dataset.filteredOut:v.dataset.filteredOut="1"})}),requestAnimationFrame(()=>{let i=e.querySelector(".ov-cell[data-current]");i&&(i.scrollIntoView({block:"center"}),i.focus({preventScroll:!0}))}),e.addEventListener("keydown",i=>{let v=i.key;if(v!=="ArrowLeft"&&v!=="ArrowRight")return;let n=[...e.querySelectorAll(".ov-cell")].filter(h=>!h.dataset.filteredOut),m=n.indexOf(document.activeElement);if(m<0)return;i.preventDefault();let l=n[m+(v==="ArrowRight"?1:-1)];l?.focus(),l?.scrollIntoView({block:"nearest"})}),()=>{M?.disconnect(),E.disconnect(),e&&(e.innerHTML="")}}export{Y as mountOverview};
230
+ :host(:not([overview])) #overview-grid { visibility: hidden; pointer-events: none; }
231
+ :host(:not([overview]):not([data-overview-warming])) #overview-grid { display: none; }
232
+ `;function X(t){if(t.querySelector(`style[${F}]`))return;let r=document.createElement("style");r.setAttribute(F,"1"),r.textContent=Q,t.appendChild(r)}function G(t){let o=t.slides[0]?.querySelector("h1");return o?Array.from(o.childNodes).map(i=>i.nodeName==="BR"?" ":i.textContent??"").join("").replace(/\s+/g," ").trim()||`Slide ${t.startIdx+1}`:`Slide ${t.startIdx+1}`}function U(t){return(t.textContent||"").replace(/\s+/g," ").trim().slice(0,400).toLowerCase()}var Z=["fill","stroke","clip-path","mask","filter","marker-start","marker-mid","marker-end","style"];function ee(t,r){let o=new Map;if(t.querySelectorAll("[id]").forEach(s=>{o.set(s.id,s.id+r),s.id=s.id+r}),o.size===0)return;let i=s=>s.replace(/url\(['"]?#([^'")]+)['"]?\)/g,(n,l)=>o.has(l)?`url(#${o.get(l)})`:n);t.querySelectorAll("*").forEach(s=>{for(let n of Z){let l=s.getAttribute(n);l?.includes("url(")&&s.setAttribute(n,i(l))}for(let n of["href","xlink:href"]){let l=s.getAttribute(n);l?.startsWith("#")&&o.has(l.slice(1))&&s.setAttribute(n,`#${o.get(l.slice(1))}`)}});let u=t.querySelectorAll("style");if(u.length){let s=n=>n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");u.forEach(n=>{let l=n.textContent??"";o.forEach((g,h)=>{l=l.replace(new RegExp(`#${s(h)}(?![\\w-])`,"g"),`#${g}`)}),n.textContent=l})}}function te(t,r){let o=t.querySelectorAll("svg");r.querySelectorAll("svg").forEach((i,u)=>{let s=o[u]?.getBoundingClientRect();if(s&&s.width>0)i.setAttribute("width",String(Math.round(s.width))),i.setAttribute("height",String(Math.round(s.height))),i.style.maxWidth="100%";else if(i.hasAttribute("viewBox")&&!i.hasAttribute("width")){let n=(i.getAttribute("viewBox")??"").split(/[\s,]+/).map(Number);n.length===4&&n[2]>0&&(i.setAttribute("width",String(n[2])),i.setAttribute("height",String(n[3])),i.style.maxWidth="100%",i.style.height="auto")}})}function re(t,r){let o=t.querySelectorAll("deck-mermaid");r.querySelectorAll("deck-mermaid").forEach((i,u)=>{let s=o[u],n=document.createElement("div");n.className="ov-mermaid-snap",n.innerHTML=s?.renderedSvg??"";let l=s?.getBoundingClientRect();l&&l.width>0&&(n.style.width=`${l.width}px`,n.style.height=`${l.height}px`),i.replaceWith(n)})}function ie(t){t.querySelectorAll("[data-click], [data-click-auto], [data-click-children], [data-click-stagger] > *").forEach(r=>{r.style.opacity="",r.style.transform="",r.style.filter="",r.style.pointerEvents="",r.querySelectorAll("path, line, polyline, polygon, circle, ellipse, rect").forEach(o=>{o.style.strokeDashoffset=""})})}function oe(t,r){let o=t.cloneNode(!0);return o.setAttribute("active",""),ie(o),te(t,o),re(t,o),ee(o,`-ov${r}`),o}async function ne(t,r,o,i){let u=i+":"+t.dataset.idx+":"+r.outerHTML,s=o.get(r);if(s?.key===u){t.insertBefore(s.thumb,t.firstChild),t.dataset.loaded="1",delete t.dataset.building;return}let n=Array.from(r.querySelectorAll("deck-mermaid")).map(f=>f.whenRendered).filter(f=>!!f);if(n.length&&await Promise.all(n).catch(()=>{}),!t.isConnected)return;s?.thumb.remove();let l=document.createElement("div");l.className="ov-thumb";let g=l.attachShadow({mode:"open"});for(let f of document.querySelectorAll('link[rel="stylesheet"], style'))g.appendChild(f.cloneNode(!0));let h=document.createElement("deck-root");h.setAttribute("data-overview-snapshot","");for(let f of["preview","no-hint","no-arrows","no-counter"])h.setAttribute(f,"");let b=r.closest("deck-root");for(let f of["width","height","class","lang","dir","style"]){let E=b?.getAttribute(f);E!=null&&h.setAttribute(f,E)}h.style.cssText+=";position:absolute;inset:0;width:100%;height:100%;",h.appendChild(oe(r,Number(t.dataset.idx))),g.appendChild(h),o.set(r,{key:u,thumb:l}),t.insertBefore(l,t.firstChild),t.dataset.loaded="1",delete t.dataset.building}function ae(t,r){let o=t.shadowRoot;if(!o)return()=>{};X(o);let i=o.querySelector("#overview-grid");i||(i=document.createElement("div"),i.id="overview-grid",o.appendChild(i));let u=K.get(t);u||(u=new Map,K.set(t,u));let s=new Set(r.slides);for(let[e,c]of u)s.has(e)||(c.thumb.remove(),u.delete(e));let n=Array.from(document.querySelectorAll('link[rel="stylesheet"], style')).filter(e=>!e.id.startsWith("rik-deck-")).map(e=>e.outerHTML).join("")+["width","height","class","lang","dir","style"].map(e=>t.getAttribute(e)).join("|"),l=n+r.slides.map(J).join("")+JSON.stringify(r.chapters.map(e=>e.startIdx)),g=R.get(t);if(g?.key===l)return i.querySelectorAll(".ov-cell").forEach(e=>{let c=Number(e.dataset.idx)===r.currentIdx;e.toggleAttribute("data-current",c),c?e.setAttribute("aria-current","true"):e.removeAttribute("aria-current")}),requestAnimationFrame(()=>{if(!t.hasAttribute("overview"))return;let e=i.querySelector(".ov-cell[data-current]");e?.scrollIntoView({block:"center"}),e?.focus({preventScroll:!0})}),g.dispose;g?.dispose(),i.innerHTML="";let h=r.slides.length,b=h>60,f=h>300?140:h>150?160:h>60?180:220;i.style.setProperty("--ov-cell-min",`${f}px`);let E=o.querySelector("#stage"),H=E?.clientWidth||window.innerWidth,Y=E?.clientHeight||window.innerHeight;i.style.setProperty("--ov-thumb-w",`${H}px`),i.style.setProperty("--ov-thumb-h",`${Y}px`);let W=new ResizeObserver(()=>{let e=i.querySelector(".ov-cell")?.clientWidth;e&&i.style.setProperty("--overview-scale",String(e/H))});W.observe(i),requestAnimationFrame(()=>{let e=i.querySelector(".ov-cell")?.clientWidth??f;i.style.setProperty("--overview-scale",String(e/H))});let S=document.createElement("div");S.className="ov-bar";let x=document.createElement("input");x.className="ov-search",x.type="search",x.placeholder=`Search ${h} slides \xB7 type to filter`,x.spellcheck=!1,S.appendChild(x);let q=document.createElement("span");q.className="ov-count",q.textContent=`${h} slides \xB7 ${r.chapters.length} chapters`,S.appendChild(q);let N=document.createElement("span");N.className="ov-hint",N.textContent="O \xB7 Esc \xB7 close",S.appendChild(N),i.appendChild(S);let C=document.createElement("div");C.className=`ov-body${b?"":" compact"}`,i.appendChild(C);let k=b?document.createElement("aside"):null;k&&(k.className="ov-aside",C.appendChild(k));let M=document.createElement("div");M.className=`ov-main${b?"":" ov-path"}`,C.appendChild(M);let $=[],z=[],P=new WeakMap,A=!1,T=[],I=!1,B=()=>{if(I||A||!T.length)return;I=!0;let e=()=>{I=!1,!A&&(T.shift()?.(),B())};"requestIdleCallback"in window?window.requestIdleCallback(e,{timeout:1e3}):setTimeout(e,32)},L=new IntersectionObserver(e=>{for(let c of e){if(!c.isIntersecting)continue;let a=c.target;if(a.dataset.loaded||a.dataset.building)continue;let p=P.get(a);if(!p)continue;a.dataset.building="1",L.unobserve(a);let d=()=>{ne(a,p,u,n).catch(w=>{let m=Number(a.dataset.tries??"0")+1;a.dataset.tries=String(m),console.warn("[rikiki/overview] thumbnail build failed",w),delete a.dataset.building,m<3&&!A&&L.observe(a)})};t.hasAttribute("overview")?d():(T.push(d),B())}},{root:null,rootMargin:"300px 0px",threshold:0});r.chapters.forEach((e,c)=>{let a=document.createElement("section");if(a.className="ov-chapter",a.id=`ov-chapter-${c}`,b){let d=document.createElement("header");d.className="ov-chapter-head";let w=document.createElement("span");w.className="ov-chapter-num",w.textContent=String(c+1).padStart(2,"0"),d.appendChild(w);let m=document.createElement("span");m.className="ov-chapter-title",m.textContent=G(e),d.appendChild(m);let v=document.createElement("span");v.className="ov-chapter-count",v.textContent=`${e.slides.length} slide${e.slides.length>1?"s":""}`,d.appendChild(v),a.appendChild(d)}let p=document.createElement("div");if(p.className="ov-row",e.slides.forEach((d,w)=>{if(!b&&w>0){let j=document.createElement("div");j.className="ov-connector",p.appendChild(j)}let m=e.startIdx+w,v=document.createElement("button");v.type="button",v.className="ov-cell",v.dataset.idx=String(m),v.dataset.search=U(d),m===r.currentIdx&&(v.dataset.current="1"),P.set(v,d),L.observe(v);let y=document.createElement("span");y.className="ov-cell-label",y.textContent=String(m+1),v.appendChild(y);let V=U(d).trim().slice(0,80);v.setAttribute("aria-label",`Slide ${m+1} of ${h}${V?` \xB7 ${V}`:""}`),m===r.currentIdx&&v.setAttribute("aria-current","true"),v.addEventListener("click",()=>r.onPick(m)),p.appendChild(v)}),a.appendChild(p),M.appendChild(a),$.push(a),k){let d=document.createElement("button");d.type="button",d.className="ov-aside-item",r.currentIdx>=e.startIdx&&r.currentIdx<e.startIdx+e.slides.length&&(d.dataset.active="1");let m=document.createElement("span");m.className="ov-aside-num",m.textContent=String(c+1).padStart(2,"0"),d.appendChild(m);let v=document.createElement("span");v.className="ov-aside-text",v.textContent=G(e);let y=document.createElement("div");y.className="ov-aside-count",y.textContent=`${e.slides.length} slide${e.slides.length>1?"s":""}`,v.appendChild(y),d.appendChild(v),d.addEventListener("click",()=>{a.scrollIntoView({behavior:"smooth",block:"start"})}),k.appendChild(d),z.push(d)}});let O=null;k&&(O=new IntersectionObserver(e=>{let c=e.filter(a=>a.isIntersecting).sort((a,p)=>a.boundingClientRect.top-p.boundingClientRect.top);if(c.length>0){let a=$.indexOf(c[0].target);a>=0&&z.forEach((p,d)=>{d===a?p.dataset.active="1":delete p.dataset.active})}},{root:M,rootMargin:"0px 0px -70% 0px",threshold:0}),$.forEach(e=>{O.observe(e)}));let _=i.querySelectorAll(".ov-cell");x.addEventListener("input",()=>{let e=x.value.trim().toLowerCase();if(!e){_.forEach(c=>{delete c.dataset.filteredOut});return}_.forEach(c=>{(c.dataset.search||"").includes(e)?delete c.dataset.filteredOut:c.dataset.filteredOut="1"})}),requestAnimationFrame(()=>{if(!t.hasAttribute("overview"))return;let e=i.querySelector(".ov-cell[data-current]");e&&(e.scrollIntoView({block:"center"}),e.focus({preventScroll:!0}))}),i.addEventListener("keydown",e=>{let c=e.key;if(c!=="ArrowLeft"&&c!=="ArrowRight")return;let a=[...i.querySelectorAll(".ov-cell")].filter(w=>!w.dataset.filteredOut),p=a.indexOf(document.activeElement);if(p<0)return;e.preventDefault();let d=a[p+(c==="ArrowRight"?1:-1)];d?.focus(),d?.scrollIntoView({block:"nearest"})});let D=()=>{A=!0,W.disconnect(),T.length=0,R.delete(t),O?.disconnect(),L.disconnect(),i&&(i.innerHTML="")};return R.set(t,{key:l,dispose:D}),D}export{ae as mountOverview};
@@ -1,5 +1,6 @@
1
- var D={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function S(e){return e==null?"":String(e).replace(/[&<>"']/g,t=>D[t])}var C="rik-presenter",T=new URL("./index.js",import.meta.url).href,a=null,p=null,u=null,h=null,f=!1;async function B(){if(h)return h;let e=window.getScreenDetails;if(!e)return null;try{return h=await e.call(window),h}catch{return null}}var g=1280,y=720;function I(e){return{left:Math.round(e.availLeft+(e.availWidth-g)/2),top:Math.round(e.availTop+(e.availHeight-y)/2)}}function M(e){let{left:t,top:r}=I(e);return`popup=yes,width=${g},height=${y},left=${t},top=${r}`}function N(e,t){let{left:r,top:n}=I(t);e.resizeTo(g,y),e.moveTo(r,n)}function E(e,t){e.requestFullscreen?.({screen:t}).then(()=>{if(!u?.has(e)){document.exitFullscreen?.().catch(()=>{});return}f=!0}).catch(()=>{})}function P(){document.fullscreenElement||(f=!1)}function A(){document.removeEventListener("fullscreenchange",P),f&&document.fullscreenElement&&document.exitFullscreen?.().catch(()=>{}),f=!1}function v(e){a?.close(),a=null,p?.close(),p=null,u?.delete(e),e.presenterActive=!1,A()}function R(e){let t=Array.from(e.children).filter(i=>i.tagName.toLowerCase().startsWith("deck-")),r=t.findIndex(i=>i.hasAttribute("active")),n=t[r]??null,d=t[r+1]??null,b=(n?.querySelector("deck-notes")?.textContent??"").trim(),o=document.querySelector('link[rel="stylesheet"][href*="rikiki"], link[rel="stylesheet"][href*="tokens"], link[rel="stylesheet"][href*="theme"]')?.href??"",l=Array.from(document.querySelectorAll("style")).map(i=>i.textContent??"").join(`
2
- `),m=document.querySelector('script[type="module"][data-rikiki-bundle]')?.textContent??"";return{current:r+1,total:t.length,slideHtml:n?.outerHTML??"",nextHtml:d?.outerHTML??null,notes:b,themeHref:o,inlineStyles:l,bundleHref:T,bundleInline:m}}function H(e){p&&p.postMessage({type:"state",state:R(e)})}var W=e=>`<!doctype html>
1
+ var R={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function S(e){return e==null?"":String(e).replace(/[&<>"']/g,n=>R[n])}var A="rik-presenter",D=new URL("./index.js",import.meta.url).href,a=null,p=null,u=null,f=null,h=!1;async function T(){if(f)return f;let e=window.getScreenDetails;if(!e)return null;try{return f=await e.call(window),f}catch{return null}}var g=1280,y=720;function C(e){return{left:Math.round(e.availLeft+(e.availWidth-g)/2),top:Math.round(e.availTop+(e.availHeight-y)/2)}}function M(e){let{left:n,top:r}=C(e);return`popup=yes,width=${g},height=${y},left=${n},top=${r}`}function $(e,n){let{left:r,top:t}=C(n);e.resizeTo(g,y),e.moveTo(r,t)}function E(e,n){e.requestFullscreen?.({screen:n}).then(()=>{if(!u?.has(e)){document.exitFullscreen?.().catch(()=>{});return}h=!0}).catch(()=>{})}function I(){document.fullscreenElement||(h=!1)}function B(){document.removeEventListener("fullscreenchange",I),h&&document.fullscreenElement&&document.exitFullscreen?.().catch(()=>{}),h=!1}function w(e){a?.close(),a=null,p?.close(),p=null,u?.delete(e),e.presenterActive=!1,B()}function P(e){let n=Array.from(e.children).filter(s=>s.tagName.toLowerCase().startsWith("deck-")),r=n.findIndex(s=>s.hasAttribute("active")),t=n[r]??null,d=n[r+1]??null,b=(t?.querySelector("deck-notes")?.textContent??"").trim(),o=document.querySelector('link[rel="stylesheet"][href*="rikiki"], link[rel="stylesheet"][href*="tokens"], link[rel="stylesheet"][href*="theme"]')?.href??"",l=Array.from(document.querySelectorAll("style")).map(s=>s.textContent??"").join(`
2
+ `),m=document.querySelector('script[type="module"][data-rikiki-bundle]')?.textContent??"";return{current:r+1,total:n.length,step:e.step,steps:Number(t?.getAttribute("steps")||t?.getAttribute("data-steps")||0),slideHtml:t?.outerHTML??"",nextHtml:d?.outerHTML??null,notes:b,themeHref:o,previewStyles:Array.from(document.querySelectorAll('link[rel="stylesheet"], style')).map(s=>s.outerHTML).join(`
3
+ `),moduleHrefs:Array.from(document.querySelectorAll('script[type="module"][src]')).map(s=>s.src),baseHref:document.baseURI,lang:document.documentElement.lang,canvasWidth:e.width,canvasHeight:e.height,inlineStyles:l,bundleHref:D,bundleInline:m}}function H(e){p&&p.postMessage({type:"state",state:P(e)})}var N=e=>`<!doctype html>
3
4
  <html lang="en">
4
5
  <head>
5
6
  <meta charset="utf-8">
@@ -56,7 +57,7 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
56
57
  container lets the iframe size against the pane in cq units. */
57
58
  #current .body { display: grid; place-items: center; container-type: size; }
58
59
  .panel iframe { border: 0; background: #0f1422; display: block; }
59
- #current-frame {
60
+ #current-viewport {
60
61
  aspect-ratio: 16 / 9;
61
62
  width: min(100cqw, calc(100cqh * 16 / 9));
62
63
  height: auto;
@@ -64,12 +65,18 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
64
65
  }
65
66
  /* Next sizes its 16:9 box from the column width (its pane row is auto), so
66
67
  the panel hugs the thumbnail instead of stretching full-height. */
67
- #next-frame {
68
+ #next-viewport {
68
69
  aspect-ratio: 16 / 9;
69
70
  width: 100%;
70
71
  height: auto;
71
72
  display: block;
72
73
  }
74
+ .preview-viewport { position: relative; overflow: hidden; }
75
+ .preview-viewport iframe {
76
+ position: absolute; top: 0; left: 0;
77
+ width: ${e.canvasWidth}px; height: ${e.canvasHeight}px;
78
+ transform-origin: top left;
79
+ }
73
80
  #notes { font-size: 17px; line-height: 1.6; white-space: pre-wrap; padding: 20px; overflow: auto; color: #e8e4f0; }
74
81
  #notes:empty::before { content: 'No notes for this slide.'; color: rgba(232,228,240,0.4); font-style: italic; }
75
82
  #footer {
@@ -101,11 +108,11 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
101
108
  <div class="grid">
102
109
  <section class="panel" id="current">
103
110
  <header>Current</header>
104
- <div class="body"><iframe id="current-frame" srcdoc=""></iframe></div>
111
+ <div class="body"><div class="preview-viewport" id="current-viewport"><iframe id="current-frame" srcdoc=""></iframe></div></div>
105
112
  </section>
106
113
  <section class="panel" id="next">
107
114
  <header>Next</header>
108
- <div class="body"><iframe id="next-frame" srcdoc=""></iframe></div>
115
+ <div class="body"><div class="preview-viewport" id="next-viewport"><iframe id="next-frame" srcdoc=""></iframe></div></div>
109
116
  </section>
110
117
  <section class="panel" id="notes-panel">
111
118
  <header>Speaker notes</header>
@@ -113,7 +120,7 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
113
120
  </section>
114
121
  <div id="footer">
115
122
  <div><span id="timer">00:00</span> <button id="timer-toggle">Pause</button> <button id="timer-reset">Reset</button></div>
116
- <div id="counter">${e.current} / ${e.total}</div>
123
+ <div><span id="counter">${e.current} / ${e.total}</span> <span id="stepper"></span></div>
117
124
  <div>
118
125
  <label class="opt"><input type="checkbox" id="opt-advance" checked> Advance on click</label>
119
126
  <span class="ghost">\xB7 P to close</span>
@@ -121,9 +128,17 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
121
128
  </div>
122
129
  </div>
123
130
  <script>
124
- const channel = new BroadcastChannel('${C}');
131
+ const channel = new BroadcastChannel('${A}');
125
132
  const current = document.getElementById('current-frame');
126
133
  const next = document.getElementById('next-frame');
134
+
135
+
136
+ const previewResize = new ResizeObserver(entries => {
137
+ for (const entry of entries) {
138
+ entry.target.querySelector('iframe').style.transform = 'scale(' + (entry.contentRect.width / ${e.canvasWidth}) + ')';
139
+ }
140
+ });
141
+ document.querySelectorAll('.preview-viewport').forEach(el => previewResize.observe(el));
127
142
  const notes = document.getElementById('notes');
128
143
  const counter = document.getElementById('counter');
129
144
  const timerEl = document.getElementById('timer');
@@ -151,31 +166,30 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
151
166
  };
152
167
  resetBtn.onclick = () => { startedAt = Date.now(); elapsed = 0; running = true; toggleBtn.textContent = 'Pause'; };
153
168
 
154
- // Presentation options \xB7 push each change to the live deck over the channel.
155
169
  document.getElementById('opt-advance').addEventListener('change', (e) => {
156
170
  channel.postMessage({ type: 'config', advanceOnClick: e.target.checked });
157
171
  });
158
172
 
159
173
  function wrapFrame(slideHtml, forward) {
160
- const themeHref = ${JSON.stringify(e.themeHref)};
161
- const inlineStyles = ${JSON.stringify(e.inlineStyles)};
174
+ const previewStyles = ${JSON.stringify(e.previewStyles).replace(/</g,"\\u003c")};
175
+ const moduleHrefs = ${JSON.stringify(e.moduleHrefs).replace(/</g,"\\u003c")};
176
+ const baseHref = ${JSON.stringify(e.baseHref).replace(/</g,"\\u003c")};
177
+ const lang = ${JSON.stringify(e.lang).replace(/</g,"\\u003c")};
162
178
  const bundleHref = ${JSON.stringify(e.bundleHref)};
163
179
  const bundleInline = ${JSON.stringify(e.bundleInline)};
164
- // Both values come from the host document, so they are only as trustworthy
165
- // as the deck \xB7 escape before they become markup. escAttr closes an attribute
166
- // breakout; escStyle stops a </style> inside the deck's own CSS (a string or
167
- // a comment) from ending the block early.
180
+
181
+
182
+
183
+
168
184
  const escAttr = (s) => s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');
169
185
  const escStyle = (s) => s.replace(/<\\/(style|script)/gi, '<\\\\/$1');
170
- const themeLink = themeHref ? '<link rel="stylesheet" href="' + escAttr(themeHref) + '">' : '';
171
- const themeStyle = inlineStyles ? '<style>' + escStyle(inlineStyles) + '</style>' : '';
172
- // Bootstrap rikiki inside the iframe so its <deck-*> elements upgrade.
173
- // \xB7 single-file deck \u2192 the framework is inlined and tagged \xB7 re-inline it
174
- // so the module base is the iframe document URL (a <script src="data:">
175
- // or a non-existent ./index.js would break new URL(rel, import.meta.url)
176
- // and abort registration). Escape any script end-tag so it can't close
177
- // this block early (this comment must avoid the literal too).
178
- // \xB7 served deck \u2192 load the real bundle URL with <script src>.
186
+
187
+
188
+
189
+
190
+
191
+
192
+
179
193
  let bundleTag;
180
194
  const esc = (c) => c.replace(/<\\/script/gi, '<\\\\/script');
181
195
  if (bundleInline) {
@@ -189,12 +203,12 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
189
203
  } else {
190
204
  bundleTag = '<script type="module" src="' + bundleHref + '"><' + '/script>';
191
205
  }
192
- // Mark the cloned slide [active] so its real component CSS applies
193
- // (:host([active]){display:flex}) instead of forcing display via !important.
206
+
207
+
194
208
  const activeSlide = slideHtml.replace(/^(\\s*<deck-[a-z-]+)/i, '$1 active');
195
- // Only the "Current" pane is a control surface \xB7 it captures key/click/wheel
196
- // and posts them to this popup window, which relays them onto the channel so
197
- // the live deck acts on them. Coords are normalised 0..1 over the iframe.
209
+
210
+
211
+
198
212
  const forwarder = forward
199
213
  ? '<scr' + 'ipt>(function(){' +
200
214
  'var post=function(o){o.source="rikiki-presenter-input";parent.postMessage(o,"*");};' +
@@ -203,47 +217,76 @@ ${e.themeHref?`<link rel="stylesheet" href="${S(e.themeHref)}">`:""}
203
217
  'addEventListener("wheel",function(e){if(e.ctrlKey||e.metaKey)return;post({type:"wheel",x:e.clientX/innerWidth,y:e.clientY/innerHeight,dx:e.deltaX,dy:e.deltaY});},{passive:true});' +
204
218
  '})();<' + '/scr' + 'ipt>'
205
219
  : '';
206
- // The deck always letterboxes into its logical canvas, so the slide keeps
207
- // its 16:9 proportions regardless of the pane's shape \xB7 just drop the
208
- // hint / nav-arrow chrome for a clean, correctly-shaped thumbnail.
209
- return '<!doctype html><html><head><meta charset="UTF-8">' + themeLink + themeStyle +
210
- bundleTag +
220
+
221
+
222
+
223
+ return '<!doctype html><html lang="' + escAttr(lang) + '"><head><meta charset="UTF-8"><base href="' + escAttr(baseHref) + '">' + previewStyles +
224
+ bundleTag + moduleHrefs.filter((href) => href !== bundleHref).map((href) => '<script type="module" src="' + escAttr(href) + '"><' + '/script>').join('') +
211
225
  '<style>html,body{margin:0;padding:0;height:100%;overflow:hidden;background:#0f1422}' +
212
226
  'deck-root{position:absolute;inset:0}</style>' +
213
- '</head><body><deck-root no-hint no-arrows no-counter preview>' + activeSlide + '</deck-root>' + forwarder + '</body></html>';
227
+ '</head><body><deck-root width="${e.canvasWidth}" height="${e.canvasHeight}" no-hint no-arrows no-counter preview data-overview-snapshot>' + activeSlide + '</deck-root>' + forwarder + '</body></html>';
214
228
  }
215
229
 
230
+
231
+ const frames = new Map();
232
+ function updateFrame(frame, html, step, forward) {
233
+ let state = frames.get(frame);
234
+ if (!state) {
235
+ state = { html, step, ready: false, painted: null };
236
+ frames.set(frame, state);
237
+ frame.addEventListener('load', () => {
238
+ state.ready = true;
239
+ paint();
240
+ });
241
+ frame.srcdoc = wrapFrame('', forward);
242
+ }
243
+ state.html = html;
244
+ state.step = step;
245
+ function paint() {
246
+ if (!state.ready) return;
247
+ const root = frame.contentDocument?.querySelector('deck-root');
248
+ if (!root) return;
249
+ if (state.painted !== state.html) {
250
+ root.innerHTML = state.html || '<div style="padding:3rem;color:white">End of deck</div>';
251
+ root.firstElementChild?.setAttribute('active', '');
252
+ state.painted = state.html;
253
+ }
254
+
255
+ Promise.resolve().then(async () => {
256
+ const elements = [root.firstElementChild, ...root.querySelectorAll('*')].filter(Boolean);
257
+ await Promise.all(elements.map(el => el.updateComplete));
258
+ elements.forEach(el => el.applyStep?.(state.step));
259
+ });
260
+ }
261
+ paint();
262
+ }
216
263
  channel.onmessage = (e) => {
217
264
  if (e.data?.type !== 'state') return;
218
265
  const s = e.data.state;
219
266
  counter.textContent = s.current + ' / ' + s.total;
267
+ document.getElementById('stepper').textContent = s.steps ? ' \xB7 \xC9tape ' + s.step + ' / ' + s.steps : '';
220
268
  notes.textContent = s.notes;
221
- if (s.slideHtml) current.srcdoc = wrapFrame(s.slideHtml, true);
222
- if (s.nextHtml) next.srcdoc = wrapFrame(s.nextHtml, false);
223
- else next.srcdoc = '<!doctype html><html><body style="background:#0f1422;color:rgba(232,228,240,0.4);display:flex;align-items:center;justify-content:center;font-family:system-ui">End of deck</body></html>';
269
+ updateFrame(current, s.slideHtml, s.step, true);
270
+ updateFrame(next, s.nextHtml, 0, false);
224
271
  };
225
272
 
226
- // Initial paint from the seed state
227
- const seed = ${JSON.stringify(e)};
273
+ const seed = ${JSON.stringify(e).replace(/</g,"\\u003c")};
228
274
  channel.postMessage({ type: 'state', state: seed });
229
275
 
230
- // Forward keys back to the main window (so the speaker can drive nav from the laptop)
231
276
  window.addEventListener('keydown', (e) => {
232
277
  if (e.target.matches && e.target.matches('input,textarea,button')) return;
233
278
  channel.postMessage({ type: 'key', key: e.key, shift: e.shiftKey });
234
279
  });
235
280
 
236
- // Relay input captured inside the "Current" preview iframe (key/click/wheel)
237
- // onto the channel \xB7 the iframe is a separate browsing context so its events
238
- // never reach this window directly \xB7 it postMessages them here instead.
281
+
282
+
239
283
  window.addEventListener('message', (e) => {
240
284
  const d = e.data;
241
285
  if (!d || d.source !== 'rikiki-presenter-input') return;
242
286
  channel.postMessage({ type: d.type, key: d.key, shift: d.shift, x: d.x, y: d.y, dx: d.dx, dy: d.dy });
243
287
  });
244
288
 
245
- // Tell main window we're alive
246
289
  channel.postMessage({ type: 'hello' });
247
290
  <\/script>
248
291
  </body>
249
- </html>`;function $(e,t){let r=document.elementFromPoint(e,t);for(;r?.shadowRoot;){let n=r.shadowRoot.elementFromPoint(e,t);if(!n||n===r)break;r=n}return r}function F(e,t,r){for(let n=e;n;n=n.parentElement){let d=getComputedStyle(n);if(r!==0&&n.scrollHeight>n.clientHeight&&/auto|scroll/.test(d.overflowY)||t!==0&&n.scrollWidth>n.clientWidth&&/auto|scroll/.test(d.overflowX))return n}return null}function O(e,t,r){let n=e.getBoundingClientRect();return{x:n.left+t*n.width,y:n.top+r*n.height}}function L(e,t){let{x:r,y:n}=O(e,t.x??.5,t.y??.5);return{x:r,y:n,target:$(r,n)??e}}function q(e){let t=(e??"all").trim();return t==="none"?"none":t===""||t==="all"?"wheel arrows aux":t.split(/\s+/).filter(r=>r!=="click").join(" ")||"none"}function U(e){if(u=u??new WeakSet,u.has(e)){v(e);return}u.add(e);let t=e.mouseNav;p=new BroadcastChannel(C),e.addEventListener("slide-change",()=>H(e)),p.addEventListener("message",s=>{let o=s.data;if(o?.type==="key"&&o.key)window.dispatchEvent(new KeyboardEvent("keydown",{key:o.key,shiftKey:!!o.shift,bubbles:!0}));else if(o?.type==="click"){let{x:l,y:m,target:i}=L(e,o),c={bubbles:!0,composed:!0,cancelable:!0,clientX:l,clientY:m,view:window,shiftKey:!!o.shift};i.dispatchEvent(new PointerEvent("pointerdown",{...c,pointerId:1,isPrimary:!0})),i.dispatchEvent(new PointerEvent("pointerup",{...c,pointerId:1,isPrimary:!0})),i.dispatchEvent(new MouseEvent("click",c))}else if(o?.type==="wheel"){let{x:l,y:m,target:i}=L(e,o),c=o.dx??0,k=o.dy??0,x=F(i,c,k);x?x.scrollBy({left:c,top:k}):i.dispatchEvent(new WheelEvent("wheel",{bubbles:!0,composed:!0,cancelable:!0,clientX:l,clientY:m,deltaX:c,deltaY:k,view:window}))}else o?.type==="config"&&typeof o.advanceOnClick=="boolean"?e.mouseNav=o.advanceOnClick?t:q(t):o?.type==="hello"&&H(e)});let r=h,n=r?.screens.find(s=>s!==r.currentScreen)??null;n?E(e,n):B().then(s=>{if(!s)return;let o=s.screens.find(l=>l!==s.currentScreen);o&&E(e,o),a&&s.currentScreen&&N(a,s.currentScreen)});let d=R(e),w=r?.currentScreen?M(r.currentScreen):`popup=yes,width=${g},height=${y}`;if(a=window.open("","rikiki-presenter",w),!a){console.warn("[rikiki/presenter] popup was blocked \xB7 allow popups for this site"),v(e);return}a.document.open(),a.document.write(W(d)),a.document.close(),e.presenterActive=!0,document.addEventListener("fullscreenchange",P);let b=setInterval(()=>{a?.closed&&(clearInterval(b),v(e))},1e3)}export{U as installPresenter};
292
+ </html>`;function W(e,n){let r=document.elementFromPoint(e,n);for(;r?.shadowRoot;){let t=r.shadowRoot.elementFromPoint(e,n);if(!t||t===r)break;r=t}return r}function q(e,n,r){for(let t=e;t;t=t.parentElement){let d=getComputedStyle(t);if(r!==0&&t.scrollHeight>t.clientHeight&&/auto|scroll/.test(d.overflowY)||n!==0&&t.scrollWidth>t.clientWidth&&/auto|scroll/.test(d.overflowX))return t}return null}function F(e,n,r){let t=e.getBoundingClientRect();return{x:t.left+n*t.width,y:t.top+r*t.height}}function L(e,n){let{x:r,y:t}=F(e,n.x??.5,n.y??.5);return{x:r,y:t,target:W(r,t)??e}}function O(e){let n=(e??"all").trim();return n==="none"?"none":n===""||n==="all"?"wheel arrows aux":n.split(/\s+/).filter(r=>r!=="click").join(" ")||"none"}function j(e){if(u=u??new WeakSet,u.has(e)){w(e);return}u.add(e);let n=e.mouseNav;p=new BroadcastChannel(A),e.addEventListener("step-change",()=>H(e)),p.addEventListener("message",i=>{let o=i.data;if(o?.type==="key"&&o.key)window.dispatchEvent(new KeyboardEvent("keydown",{key:o.key,shiftKey:!!o.shift,bubbles:!0}));else if(o?.type==="click"){let{x:l,y:m,target:s}=L(e,o),c={bubbles:!0,composed:!0,cancelable:!0,clientX:l,clientY:m,view:window,shiftKey:!!o.shift};s.dispatchEvent(new PointerEvent("pointerdown",{...c,pointerId:1,isPrimary:!0})),s.dispatchEvent(new PointerEvent("pointerup",{...c,pointerId:1,isPrimary:!0})),s.dispatchEvent(new MouseEvent("click",c))}else if(o?.type==="wheel"){let{x:l,y:m,target:s}=L(e,o),c=o.dx??0,v=o.dy??0,x=q(s,c,v);x?x.scrollBy({left:c,top:v}):s.dispatchEvent(new WheelEvent("wheel",{bubbles:!0,composed:!0,cancelable:!0,clientX:l,clientY:m,deltaX:c,deltaY:v,view:window}))}else o?.type==="config"&&typeof o.advanceOnClick=="boolean"?e.mouseNav=o.advanceOnClick?n:O(n):o?.type==="hello"&&H(e)});let r=f,t=r?.screens.find(i=>i!==r.currentScreen)??null;t?E(e,t):T().then(i=>{if(!i)return;let o=i.screens.find(l=>l!==i.currentScreen);o&&E(e,o),a&&i.currentScreen&&$(a,i.currentScreen)});let d=P(e),k=r?.currentScreen?M(r.currentScreen):`popup=yes,width=${g},height=${y}`;if(a=window.open("","rikiki-presenter",k),!a){console.warn("[rikiki/presenter] popup was blocked \xB7 allow popups for this site"),w(e);return}a.document.open(),a.document.write(N(d)),a.document.close(),e.presenterActive=!0,document.addEventListener("fullscreenchange",I);let b=setInterval(()=>{a?.closed&&(clearInterval(b),w(e))},1e3)}export{j as installPresenter};
@@ -35,6 +35,9 @@ export interface DeckPlugin {
35
35
  navigate?(to: number, ctx: DeckContext, proceed: () => void): boolean | void;
36
36
  }
37
37
  export declare class DeckRoot extends LitElement {
38
+ /** Internal overview surface: author selectors still see deck-root, but the
39
+ * outer thumbnail owns sizing and no presentation runtime is needed. */
40
+ private get _overviewSnapshot();
38
41
  static styles: import("lit").CSSResult;
39
42
  current: number;
40
43
  step: number;
@@ -193,6 +196,16 @@ export declare class DeckRoot extends LitElement {
193
196
  * surface · removing the override lets the bands fall back to that same
194
197
  * surface, which stays seamless too. */
195
198
  private _applyLetterbox;
199
+ /** A slide can reach the engine before its own module does · an opt-in
200
+ * component loads from its own script tag, and nothing orders the two.
201
+ * Until it upgrades it has no shadow DOM and reports a TRANSPARENT
202
+ * background, so the read above finds nothing and the bands keep the page
203
+ * surface. This is the only measurement in the engine with no observer
204
+ * behind it, so without this it would never be taken again.
205
+ *
206
+ * Same shape as _stepWatcher below, which catches a step count that
207
+ * arrives late for the same reason. */
208
+ private _repaintLetterboxWhenDefined;
196
209
  /** The scaling baseline is a framework concern, not a theme one: inject it
197
210
  * globally so any theme (or none) gets it. The rem unit tracks the logical
198
211
  * canvas height · the #stage transform does the responsive scaling · and the
@@ -323,9 +336,7 @@ export declare class DeckRoot extends LitElement {
323
336
  private _goToCoords;
324
337
  private _applyActive;
325
338
  private _applyStep;
326
- /** The bottom-right slide counter is noise in modes where it shouldn't show:
327
- * the overview grid, a black/white blanked screen, and the cover slide (the
328
- * title slide has no business carrying a page number). */
339
+ /** Keep numbering on all slide layouts; hide it only in overlay modes. */
329
340
  private _counterHidden;
330
341
  private _updateUI;
331
342
  updated(changed: PropertyValues<this>): void;